First published on TECHNET on Oct 18, 2016
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.interop... 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.interop... workflowInteropService.StartWorkflow(workflowAssociation.Name, corId, list.Id, itemGuid, new Dictionary<string, object>());
clientContext.ExecuteQuery();