Saturday, July 22, 2017

Call any SharePoint REST API from Microsoft Flow

EDIT:
There is a much better way to call the SharePoint REST APIs now. A new action has been added to Microsoft Flow to do just that easily. See https://sergeluca.wordpress.com/2018/05/03/assign-unique-permissions-to-a-document-with-the-new-send-an-http-request-to-sharepoint-action-how-to-use-the-sharepoint-rest-api-in-flow/ for more information.

Case:
You want to do an action on SharePoint Online from a Flow. But the action, that is supported in the SP REST API, is not yet available as an easily configurable action inside Microsoft Flow.
So you think, I should be able to use the HTTP action for this.

Well, you're right!

But how do you then authenticate to SharePoint Online? I tried to get a token from the supported SharePoint actions in Flow but these turn out to have been *sanitized*, ie. not usable in other actions.

I tried a bunch of things including using the OAuth authentication setting on the HTTP actions. But that required filling in the rather meaningless (to me at least) parameter Audience. I suppose this should be the App ID URI of microsoft flow in your AAD Tenant, but I wasn't able to find it.

Thank god for this article that I (re)found after useless trial and error: Access Sharepoint Online Using Postman by Shantha Kumar

The article explains in great deal how to authenticate and perform a call to any REST API endpoint inside SharePoint.

This is the general gist:
1. Register an App in SharePoint through the pages /_layouts/15/appregnew.aspx and appinv.aspx
This will give you a client-id, client-secret and on the page /_layouts/15/appprincipals.aspx you can find your tenant id (the guid after the @ sign)
2. Perform a HTTP post to https://accounts.accesscontrol.windows.net/<tenantid_guid>/tokens/OAuth/2
with headers
 Content-Type:application/x-www-form-urlencoded
and in the body (remember the request is URL encoded, so it's just one big string, not JSON) a string like this:
grant_type=client_credentials&client_id=<apponlyclientid>@<tenantidguid>&client_secret=<clientsecret>&resource=00000003-0000-0ff1-ce00-000000000000/<yoursubdmain>.sharepoint.com@<tenantidguid>
3. Get the access token for the output of the previous HTTP action. Use a compose action, and enter something like this:
"@outputs('HTTP_2').body.access_token" where 'HTTP_2' is the name of your previous HTTP action with spaces replaced by underscores.
4.
Use the output of the HTTP compose (that contains the Bearer token) as input for any REST API call into sharepoint.
For example, Perform a HTTP Post to https://<yoursubdomain>.sharepoint.com/sites/Provisioning/_api/web/lists/getbytitle('Documents')/items(2)/roleassignments/addroleassignment(principalid=23,roledefid=1073741827)
with the following headers:
Accept:application/json;odata=verbose
Authorization:Bearer [OutputFromComposeAction]
This will add List item permissions on a list item (if you have broken role inheritance on this item already and are passing valid values for list item id, principalid and roledefid)

Here are some screenshots how to do that in Microsoft Flow:
Before




After