How to get user id in plugin?

Inside the plugin context there are two user identifiers,

  • InitiatingUserId , which returns the identifier of the user who actually activated the plugin.
  • UserId , which returns the identifier of the user on which the plugin actually runs. (this is the user specified when registering the plugin or the caller, if he is registered to run as the caller)

But I'm interested in the third user identifier, the personified identifier of the OrganizationServiceProxy user that made the call.

Suppose I have an ASP.Net website running with an AD AD CRM account, and any calls made to CRM use impersonation by looking at the CRM ID of the user who is currently logged in.

This is great for selecting and updating, the user can see / update what they have. But ... if I create a plugin that starts when a specific object is updated, how can I find the user id of the impersonated user on the Asp website from the plugin?

+6
source share
3 answers

As far as I understand the situation, you can get the user ID of the issued user, but not the authenticated user. Listed below are some scenarios that should hopefully clarify behavior (tested in UR11 and UR12):

  • Identified in CRM as User A , personifying User B. The plugin is not registered to impersonate any particular user (ie ImpersonatingUserId for the plugin step is set to null (from the registration tool of the plugin “Launch in user context” it will be set to “Call user”). An example with OrganizationServiceProxy authenticate as User A where proxyService.CallerId User B.
    • PluginContext.UserId = User B
    • PluginContext.InitiatingUserId = User B
    • createdonbehalfby (or modifiedonbehalfby ) = User A
  • Identified in CRM as User A , personifying User B. The plugin is registered to impersonate user C. (i.e. the ImpersonatingUserId of the plugin step is set to user C (user C will be installed from the plugin registration tool "Launch in user context")). An example would be with OrganizationServiceProxy authenticated as User A , where proxyService.CallerId is User B.
    • PluginContext.UserId = User C
    • PluginContext.InitiatingUserId = User B
    • createdonbehalfby (or modifiedonbehalfby ) = User A

Scenario # 1 confuses me a little, because I vaguely remember that I work differently. This should mean that when the CallerId property CallerId set, impersonation takes place in a different place than in Scenario # 2. However, you can see that in Scenario # 2 we seem to have achieved the expected result.

The steps that I used to create this result were as follows:

  • Create a console application and link Microsoft.Xrm.Sdk and Microsoft.Crm.Sdk.Proxy . Create a new OrganizationServiceProxy object where the authenticated user is User A. Set CallerId as Guid representing User B.
  • Create a super simple plugin that just throws an exception, the first chance it gets as follows:

     throw new Exception(string.Format("Initiating Id: {0}, User Id: {1}", context.InitiatingUserId, context.UserId)); 
+3
source

Just wanted to clarify that the GotDibb data is correct, although my question contradicts this.

I created the UserIdTest plugin as follows

 public void Execute(IServiceProvider serviceProvider) { var context = serviceProvider.GetContext(); var service = serviceProvider.GetService(context); var iUser = service.Retrieve("systemuser", context.InitiatingUserId, new ColumnSet("fullname")); var uUser = service.Retrieve("systemuser", context.UserId, new ColumnSet("fullname")); throw new Exception(string.Format("Initiating: {0}, User: {1}", iUser.GetAttributeValue<string>("fullname"), uUser.GetAttributeValue<string>("fullname"))); } 

I ran the same tests as GotDibbs and got the same answers that confused me, because I would not ask if I received any other answer. But then I realized that the problem I saw was caused by a recursive plugin.

The first call to the plugin worked as expected, but when the plugin initiated another call to the plugin, it used the user credentials for the Context plugin (which makes sense) and lost the authenticated user IDs. Here is a table that hopefully helps you figure out what happens.

First for the initial plugin call:

 +--------------------+------------ +----------------------+----------------------------------------+ | Org Service | Org Service | Plugin Step Run | Results | | Client Credentials | CallerId | in User Context | | +--------------------+------------ +----------------------+----------------------------------------+ | | | | InitiaitingUser : ServiceAccount | | ServiceAccount | None | PluginServiceAccount | | | | | | UserId : PluginServiceAccount | +--------------------+------------ +----------------------+----------------------------------------+ | | | | InitiaitingUser : UserBob | | ServiceAccount | UserBob | PluginServiceAccount | | | | | | UserId : PluginServiceAccount | +--------------------+------------ +----------------------+----------------------------------------+ 

And the second for Plugin Depth> 1

 +--------------------+------------ +----------------------+----------------------------------------+ | Org Service | Org Service | Plugin Step Run | Results | | Client Credentials | CallerId | in User Context | | +--------------------+-------------+----------------------+----------------------------------------+ | | | | InitiaitingUser : PluginServiceAccount | | ServiceAccount | None | PluginServiceAccount | | | | | | UserId : PluginServiceAccount | +--------------------+-------------+----------------------+----------------------------------------+ | | | | InitiaitingUser : PluginServiceAccount | | ServiceAccount | UserBob | PluginServiceAccount | | | | | | UserId : PluginServiceAccount | +--------------------+-------------+----------------------+----------------------------------------+ 
0
source

The same problem is also relevant in CRM 2013 and probably has the same solution:

Assuming the script in which the plugin is registered to run in the context of the calling user, the launch context values ​​of ProjectingUserId and UserId will be the same.

This is true even if the client has established a connection by overriding CallerId - in this case both values ​​will represent the specified CallerId value instead of the identifier of the user who has been authenticated.

So how to get the actual caller id inside the plugin? The input phase is simple, just mark createdonbehalfby or modifiedonbehalfby in the image after execution. The preliminary operation is not so obvious, since these values ​​do not exist anywhere, but the trick is simple.

Inside the plugin, create a new IOrganizationService, where UserId is NULL, not context.UserId or context.InitiatingUserId, but instead just null. Then, using this service, execute the WhoAmI request, and the response will contain the GUID of the authenticated user who made the service call, not the identifier of the specified CallerId.

It turns out that IOrganizationServiceFactory has a private field that contains this value (AdministratorId), but since it is private, it is not readable, so this workaround will work at the expense of extra overhead.

-1
source

Source: https://habr.com/ru/post/945725/


All Articles