Dynamics CRM 2016 (On-Premise) calling user context - dynamics-crm

I'm working on a custom plug-in (non-sandboxed) in a CRM2016 on-prem to interface with an internal webAPI.
When I run this piece of code, it is returning the CRM App Pool user and not my user name:
(System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
Is this expected and normal? If it is, how do you impersonate the calling user for external calls.
Thanks.

Yes that is normal, synchronous plugins run on the web server, so getting the IIS App Pool user is expected. If the plugin is running asynchronously its runs on the back end asynchronous service so you would probably get a different service account.
You could examine the plugin execution context (IPluginExecutionContext) to get eitherInitiatingUserId or UserId, which is the CRM GUID of the system user account under which the plugin is executing - depending how on the plugin is executed and registered this can give you the CRM identity of the user who started the plugin.
Jeff describes this within; How to get current user record in CRM plugin?
The information is available in the PluginExecutionContext. The code
below is from the Execute method your plugin must implement.
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
Guid userId = context.InitiatingUserId;
}
FYI, the context also has a "UserId" property that may or may not be
the same as the InitiatingUserId. If your plugin step registration
"Run in Users's Context" field has the value "Calling User", then they
will be the same. If you have specified a user in the "Run in User's
Context" field, then the UserId field will contain the user ID of the
person you specify and the InitiatingUserId will be the actual CRM
user whose action triggered the plugin. Sounds like you're looking for
the InitiatingUserId.
Or perhaps you could use another indicator, such as whoever last modified some record. You could then lookup their details in CRM, e.g. to get their domain name.
Depending on how you authenticate with the external service this might help to impersonate the user. Otherwise there as far as I know there is no easy way to get the users security token for example, CRM doesn't really expose that information.

Related

Can I register a plug-in on the user login event in Dynamics CRM?

I want to register a plug-in in Plugin Registration Tool when a user logs in to Dynamics CRM. For this I don't want to use Audit. I want to catch the login event directly.
If this is not possible, is there any log that is create in every login of the user.
As far as I know, No you cannot do so.
But CRM has provided few different ways where you can check which users are currently working/logged in.
Go to Settings--> System Settings--> Auditing and then you can enable audit user access.
Above will enable for all users and then you can see audit data as below.
Ref for 1st option https://blogs.msdn.microsoft.com/emeadcrmsupport/2015/07/09/dynamics-crm-audit-user-access-data/
Now another way you can do so it visit url https://admin.powerplatform.microsoft.com/
Here go under analytics and then common data service. You wil get most of the info
High level design of what I would do:
Make/identify a default dashboard for all users and keep a HTML web resource in there
Web resource can have a method to invoke Xrm.WebApi.online.execute for executing a Custom Action by passing parameter to include IP, Lat, Lon, Browser details. Read more
Register a plugin on Custom Action message to trigger and achieve what you want there

Check user roles from Application Service

i'm implementing Application Service that sends statistical data to home page (dashboard application page).
Based on User's Role (the service needs authentication) i would extract/aggregate data from database using WhereIf() based on is role
In particular if user is administrator, I will not apply a data extraction filter using WhereIf()
To do that i've injected IAbpSession inside service constructor to be able to give userid, but how can i ckeck if user is an administrator?
You can check if current user is an administrator by checking the associated roles of that user. You must inject the UserManager which has several methods for role checking. One of them is IsInRole(userId, roleName).

Authenticating dynamics CRM plugin to access Web API 2 methods

I have written a plugin in dynamics CRM. This plugin accesses a few Web API 2 methods that are deployed in Azure cloud (via HTTPS). The plug-in is triggered when a contact data in the CRM changes. Many CRM account holders will update the contact data.
I am going to hard code a 'secret key' (a one time generated Guid) in the plug-in and send this key every time I access the web api methods. I'll validate this guid in the web api methods to prevent un-authorized access.
I do not like to store the secret key (guid) in the source code.
Questions
What are my alternatives if do not want to 'hard code' the secret key?
What are the security flaws in this approach?
Note
In general, all my Web APIs are authenticated by a custom authentication web api filter, but the Web APIs that are accessed from the plugin are not part of the custom authentication.
CRM version is 2013
As the previous answers states, the first option is to store your information in a configuration custom entity that you can retrieve from your plugin. Those records are going to be protected by the CRM security model, so if your plugin is running in the calling user context you will need to make sure that the users have privileges to read that information (not really a good idea) or change the plugin to be executed under an admin user context.
Another option is to use Secure/Unsecure Configuration:
Those are two (string) parameters that you can configure within the step and you will be able to read them from the plugin. I would say that the secure configuration fits your requirement but give it a look. You can also easily find how to implement it (example).
The third and last option that I can think of, is to create an XML WebResource and read it from the plugin. Again, you will need to make sure that the user context under the plugin is running has access to it.
I don't think this approach will ever be secure.
It's possible to extract the plugin assembly from CRM. Someone could then disassemble the assembly and find the Guid. Effectively your password is stored in plain text.
At the very least you could store the user name/password/secret key in a CRM record. The CRM record can then be protected with CRM security.
You are probably better off implementing the authentication 'normally'.

How to create multiple entities of same type in a single go in CRM online?

I am integrating MS Dynamics CRM online with my ASP.Net MVC application. I am creating a synchronization process between both. I'm stuck at the point where
I need to check if user has entered valid CRM credentials ie. server address, domain, username and password etc. I am not sure which class is to use for that?
I want to create multiple entities of same type in a single go in CRM online from my Application. Currently I am using ServiceProxy's Create() method to do so . How can I create , for instance, 10 contacts in a single request ?
Is there any way to send list of objects to CRM server and create
them there?
To check I believe the easiest way is just execute call for example of WhoAmI message. If it would not throw an exception - that will mean that credentials are correct.
You should look at ExecuteMultiple message.

FileNet 5.2 subscription run as user

IBM Knowledge Center states that
Server disables security access checks during subscription execution
but does not mention the user credentials the code uses to execute which you need to know in order to map user RunAs roles on the application server.
What user credentials does FileNet use to execute event action code?
As I understand, when you create async subscription it will be executed under p8boostrap user.
And it will keep user context when you execute syncronious subscription.
But you can check it for sure.
It is using the user who triggered the action. E.g. if a user changes a property of a document (let's say DocumentTitle because it is always there) and clicks save, then an update event will be triggered which launches the subscription (if subscribed to the update event) which launches the action. Use synchronous for short running tasks, you can immediately show the update to the user. With asynchronous the user will have to click "Refresh".
Security can be a pain if not planned carefully at the beginning, for the action to be executed, the user has to have rights for the subscription, action event, document class etc. basically for everything involved or the user will get a cryptic error message when trying to modify the DocumentTitle.
Source: personal experience, sorry no official reference, if in doubt verify first.

Resources