Use Microsoft Graph to Set Granular Permissions to SharePoint Online Sites for Azure AD Application
Tags: azure, sharepoint, powershell, m365
Published: 2021-02-09 06:57:53

I recently put out a Twitter post about the upcoming capability 
that allows you to apply granular permissions to SharePoint Online Sites for Azure AD Applications.  

{% twitter 1349747161504882688 %}

This capability is now live and available in the Microsoft Graph API (both v1.0 and Beta). Find the API reference on [Microsoft Graph documentation](https://docs.microsoft.com/en-us/graph/api/resources/permission?view=graph-rest-1.0). I have seen a lot of our customers rely on the legacy 'Access Control Services' (ACS) based apps (apps registered using /_layouts/15/appregnew.aspx page) to meet the site level/granular permissions requirements. With this update you can now stop doing that and embrace the modern way using Microsoft Graph.

In this blog I will show how this is accomplished using PowerShell and Microsoft Graph REST API calls.

The current implementation feels like a MVP('minimal viable product') of a long term solid plan from Microsoft. Therefore, at the moment there is no UI/UX for admins to manage (add/remove permissions at) the individual site level permissions. It's only possible through Microsoft Graph API. You will need two apps to accomplish this.

First is the Azure AD application (let's call it 'client-app') registered that needs to be given app-only permissions to select few sites (as against to all sites in the tenant). First step is to navigate to the "API Permissions" for that app. Select "Application permissions" box. Then select "Sites.Selected" permission scope listed under "Sites" category.
![image](https://dev-to-uploads.s3.amazonaws.com/i/zcroszjn5a5ulm1dbsyd.png)

You need another Azure AD application (let's call it 'admin-app') that has 'Sites.FullControl.All' app-only permissions. Assume this is created and managed by your IT Admins. IT admin will use this application (as a helper utility) to call Microsoft Graph and assign 'client-app' the permissions (read or write) for each site that it needs access. In this way the 'client-app' will be able to make queries only to those set of sites. Microsoft graph is updated to support this capability. To add/remove permissions at site collection level, you need to use the /sites/{site-id}/permissions REST API.
Here is an example:
>https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com,ab37ac98-a777-4444-b90f-20e2a8728caf,faaf89c8-4444-4639-978f-39e07847b61a/permissions

Here is a sample PowerShell script to enumerate existing site level permissions using Microsoft Graph
{% gist https://gist.github.com/svarukala/d8d2903212626fb8efc1ace4a9fa10ff %}
>NOTE: When we enumerate the granular permissions, its not showing the role (read/write) details. It's showing the unique perm id, display name and client app id. This might be a temporary gap in the functionality.

Here is a script sample to add granular permissions to a site using Microsoft Graph:
{% gist https://gist.github.com/svarukala/0fe3ebcf483d645bb501e7e987087b0b %}

Here is a script to remove all granular permissions or selected granular permissions based on the app id:
{% gist https://gist.github.com/svarukala/59831127fac6f23de869fdfa9e5b808b %}

I created a sample script to finally test this out. This sample script enumerates all the lists in a given SPO site. Below image shows the script failing before giving the granular permissions:
![image](https://dev-to-uploads.s3.amazonaws.com/i/2g1o1z51j0rarz88s7ne.png)

Now I ran the Add-SPOSiteGranularPermission script giving my client-app 'read' permissions to the site. Here is the output from the script:
![image](https://dev-to-uploads.s3.amazonaws.com/i/brvt9lxnu24ycumpw2mn.png)
  

Below image shows the same script now successful after giving the granular permissions on the site:
![image](https://dev-to-uploads.s3.amazonaws.com/i/id8qmcg6tuvstguzvo3y.png)

Here is the sample script that I used for my sample run:
{% gist https://gist.github.com/svarukala/09a35eb344f998cc09ec029b5086d406 %}

Some of the limitations I see in the current state:
1. Thie granular permissions is limited to application permissions (app-only) for an Azure AD app. 
2. There is no UI/UX to manage the granular permissions
3. There is currently no endpoint to list out sites that has granular permissions enabled for a given AAD app
4. Site collection level seems to be the most granular it can go.

[Jeremy Kelley (Microsoft PM)](https://twitter.com/Fizzlenik) presented on this topic in February's Microsoft Graph community call. He answered a bunch of questions and also hinted that this capability is just beginning and it has a long way to go. You can access the recording [here](https://developer.microsoft.com/en-us/office/blogs/microsoft-graph-community-call-february-2-2021/).

Finally I am working on a full blown script to manage the site level permissions in bulk. You can retrieve, add, remove permissions by supplying a CSV file as input. I will update the link here once that is ready.

Please leave any comments, questions or feedback.