Programmatically Enable Trust for Built-In SharePoint Workflow Apps
- by Parlae Solutions Developer
- September 2015
We completed a project for which a company requested extranet portals for its clients. The portals provide information for each client on their various projects. We developed a series of workflows and site templates to enable the creation of a site collection, per client, which contains subwebs for each project.
We developed these workflows as SharePoint 2013 Workflows but quickly discovered permissions issues which we had never before encountered. With the advent of SharePoint 2013 Workflows, Microsoft removed workflows from the SharePoint farm to a Windows Azure Workflow platform. This shift reflects the inexorable march toward cloud-based architectures, and its implementation requires rethinking development techniques that were trivial previously.
One major consequence of the new architecture is the de-emphasis on custom code activities. On-premise deployments can host them, but cloud-based hosts will not. Even on premise, custom code is discouraged, and Microsoft made little effort to ease its deployment. (See section Deployment Steps. Note: Advice contained within is both accurate and terrible--do not follow it even though it works.)
In earlier versions of SharePoint, when a workflow required greater privileges, the developer invoked an elevated delegate (i.e. RunWithElevatedPrivileges) in the code-behind. However, remote workflows now run in the context of a built-in app (i.e. Workflow) on SharePoint. Without custom code and under this limited app context, certain quotidian tasks (e.g. checking group membership) become more difficult.
SharePoint 2013 Workflows are declarative and included among the built-in activities is the App-Only Step. This activity permits the workflow to run in the context of a site owner. We have included Microsoft’s instructions to successfully execute the activity as a linked image below:
As you can see, the process is extensive, and Microsoft provides instructions only through the GUI. (Many, many, many blogs and forums reproduce Microsoft’s instructions, often using Microsoft’s own screenshots. This post shows only one more image from Microsoft.) It is a reliable method to enable App-Only Step, and it would work fine as a one-off effort upon initial setup. However, if you jump to the step at Site app permissions—wherein we copy/paste part of a string—Microsoft omits the URL:
If we browse to our dev site, we can see the URL:
Note in the query string that the Scope parameter limits us to the site collection web. After removing it--
--we can see that each subweb also has its own Workflow app. There may be great benefits to each web having a dedicated Workflow app, but in a project like our client portal, it had the potential for being a complete non-starter. Each time our client generated another site collection for its clients and each project under them, someone would have to run through Microsoft’s instructions for elevated permissions. This would be cumbersome and, frankly, nonsensical given our client’s needs.
In researching the problem, we initially found a useful (yet unreliable) script that opened an instance of IE, browsed the necessary SharePoint admin pages, parsed the DOM for needed values and events, initiated the necessary copy/paste and form submissions while waiting in-between for postbacks. Full execution could take as long as thirty seconds. Obviously, we could not rely on this in production for any number of reasons.
Luckily, we discovered a misbegotten post on a forum which strips and references a bit of sample code from MSDN which we have not, as yet, located (i.e. TrustWorkflowApp). With a partial guide, we developed the following bit of code to programmatically trust the Workflow app at its given scope:
After site creation, we activate a web-level feature which retrieves the app principals’ info. After parsing each name identifier, we get the principal itself to determine whether it is the Workflow app. We then get the Workflow app’s permissions from both the principals manager and the site subscription to determine whether the app has standard or trusted privileges. If it does not have full control, we add a site subscription then, regrettably, sleep the thread because you never can tell how long it takes the subscription to complete. There is a risk of an infinite loop, but in theory, execution cannot have made it into the loop without all the objects having everything they need to finish.
This bit of code burned the better part of an afternoon for us, but we hope it will save you some headaches whenever you look to avoid following that interminable Microsoft article.
Please share if you thought this post was worth reading!