Impersonation in C# App for D365

We can impersonate a user in console app or any 3rd party code my passing the Guid of impersonated user in the CallerId field of CrmServiceClient object. Below is sample code:

If we are retrieving a FLS field then the impersonating user and impersonated user both should have access to the field. If either doesn’t have access then no value is returned.

static void Main(string[] args)
{
    string ConnectionStringOAuth = @"AuthType = OAuth;
                                     Username = xxxxxx@xxxxxx.onmicrosoft.com;
                                     Password = xxxxxx;
                                     Integrated Security=true;
                                     Url = https://xxxxxx.crm.dynamics.com;
                                     AppId = xxxxxx;
                                     RedirectUri = https://xxxxxxxx;
                                     LoginPrompt=Auto";
    CrmServiceClient svc = new CrmServiceClient(ConnectionStringOAuth);
    svc.CallerId = Guid.Parse("{60FBEAFB-7724-EB11-A813-000D3A569CF5}");

    var cs = svc.RetrieveMultiple(new QueryExpression("ps_configurationsetting")
    {
          ColumnSet = new ColumnSet(true),
          Criteria =   {
                          Filters =
                          {
                                new FilterExpression
                                {
                                   FilterOperator = LogicalOperator.And,
                                   Conditions = {
                                         new ConditionExpression("ps_key", ConditionOperator.Equal, "azurekey")
                                   }
                                 }
                          }
                    }
     });
     string value = cs.Entities.Count != 0 ?
     (cs.Entities[0].Attributes.Contains("ps_value") ?
     cs.Entities[0].Attributes["ps_value"].ToString() : string.Empty) :
 string.Empty;

     Entity task = new Entity("task")
     {
          Attributes = new AttributeCollection()
          {
               new KeyValuePair<string, object>("regardingobjectid",
               new EntityReference("contact", Guid.Parse("{87D4EF7F-DE38-EB11-A813-0022481BFEB4}"))),
               new KeyValuePair<string, object>("subject", value)
          }
     };
     var newRecord = svc.Create(task);
     Console.ReadLine();
}

Possible Error :

contextUserId=<impersonating userid> is missing privilege <Privilege GUID>. Parameter’user’=<impersonated userid>, callerId=<impersonated userid>.

This error will occur if privilege prvActOnBehalfOfAnotherUser is missing on impersonating user.

Impersonation in a plugin D365

We can impersonate any user in plugin code by passing user GUID to CreateOrganizationService of IOrganizationServiceFactory. Below is sample plugin code. The code is impersonating with user GUID and then creating task.

public void Execute(IServiceProvider serviceProvider)
        {
            var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                var serviceFactory =
                    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service;

                try
                {
                    service = serviceFactory.CreateOrganizationService(new Guid("60FBEAFB7724EB11A813000D3A569CF5"));
                    CreateTask(service, context);
                }

                catch (FaultException<OrganizationServiceFault> ex)
                {
                    throw new InvalidPluginExecutionException("An error occurred.", ex);
                }

                catch (Exception ex)
                {
                    tracingService.Trace("Error: {0}", ex.ToString());
                    throw;
                }
            }
        }

In create task function, we are retrieving value from FLS field and then creating a task with that description. If user which we are impersonating doesn’t have access to FLS, we will get ‘Access Denied’ in description.

public void CreateTask(IOrganizationService service, IPluginExecutionContext context)
{
       var cs = service.RetrieveMultiple(new QueryExpression("ps_configurationsetting")
       {
            ColumnSet = new ColumnSet(true),
            Criteria =   {
                                Filters =
                                {
                                    new FilterExpression
                                    {
                                        FilterOperator = LogicalOperator.And,
                                        Conditions = {
                                            new ConditionExpression("ps_key", ConditionOperator.Equal, "azurekey")
                                        }
                                    }
                                }
                    }
        });

        string securevalue = cs.Entities.Count != 0 ?
            (cs.Entities[0].Attributes.Contains("ps_securevalue") ?
            cs.Entities[0].Attributes["ps_securevalue"].ToString() : "Access Denied") :
            string.Empty;

        Entity followupTask = new Entity("task");
        followupTask["subject"] = "Send e-mail .";
        followupTask["description"] = securevalue;
        followupTask["scheduledstart"] = DateTime.Now.AddDays(7);
        followupTask["scheduledend"] = DateTime.Now.AddDays(7);
        followupTask["category"] = context.PrimaryEntityName;
        if (context.OutputParameters.Contains("id"))
        {
            Guid regardingobjectid = new Guid(context.OutputParameters["id"].ToString());
            string regardingobjectidType = "contact";
            followupTask["regardingobjectid"] = new EntityReference(regardingobjectidType, regardingobjectid);
        }
        service.Create(followupTask);
}

%d bloggers like this: