This post is a contribution from Manish Joshi, an engineer with the SharePoint Developer Support team
There seems to be a check in SharePoint when starting a workflow using CSOM if SharePoint 2013 workflow is started using the App-Only context – if yes, throw Access Denied exception and log this exception.
So there is no other way than to start a SharePoint 2013 workflow in CSOM except using the App+User context
Following code illustrates using an app only access token to create a ClientContext and start the SharePoint 2013 workflow in CSOM.
- Get the Client Context using the App only Access Token
// get app only access token by passing the windows identity as null string appOnlyAccessToken = TokenHelper.GetS2SAccessTokenWithWindowsIdentity(hostWeb, null); return TokenHelper.GetClientContextWithAccessToken(hostWeb.ToString(), appOnlyAccessToken);
- Invoke the workflow using the Client Context retrieved
// start the workflow using the CSOM APIs and the client context retrieved previously var workflowManager = new WorkflowServicesManager(clientContext, clientContext.Web); InteropService workflowInteropService = workflowManager.GetWorkflowInteropService(); // call the StartWorkflow method - https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.workflowservices.interopservice.startworkflow.aspx workflowInteropService.StartWorkflow(workflowAssociation.Name, corId, list.Id, itemGuid, new Dictionary<string, object>()); clientContext.ExecuteQuery();
The above code will throw AccessDenied exception.
To get this to work the code needs to be changed as below.
- Get the Client Context for App + User context access token
// pass a valid windows identity to get app + user context string appUserAccessToken = TokenHelper.GetS2SAccessTokenWithWindowsIdentity(hostWeb, windowsIdentity); return TokenHelper.GetClientContextWithAccessToken(hostWeb.ToString(), appUserAccessToken);
- Invoke the workflow using the Client Context retrieved
// start the workflow using the CSOM APIs and the client context retrieved previously var workflowManager = new WorkflowServicesManager(clientContext, clientContext.Web); InteropService workflowInteropService = workflowManager.GetWorkflowInteropService(); // call the StartWorkflow method - https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.workflowservices.interopservice.startworkflow.aspx workflowInteropService.StartWorkflow(workflowAssociation.Name, corId, list.Id, itemGuid, new Dictionary<string, object>()); clientContext.ExecuteQuery();