The Microsoft Graph team have recently added functionality to allow an app access to just specific SharePoint site collections (Sites.Selected) rather than all. Historically to do anything as an app with Microsoft Graph in SharePoint the only permission levels available have been to allow access to all sites in the tenant i.e. Sites.FullControl.All. Giving the app permission to ALL site collections has meant security focussed tenant administrators are unable to grant this level of access rather than just the site collections(s) the app needs to work on.
There is now a new granular/resource specific permission level in Microsoft Graph named Sites.Selected which allows applications to be given Read or Write permissions to specific known site collections rather than all site collections. Once an app is given Sites.Selected permission it will by default have no permission to any SharePoint site collections. and the app will then need to be explicitly added to the permissions object of the SharePoint site through Microsoft Graph/PnP.PowerShell. At the moment the permissions can only be applied via code and there is no user interface to administrate via a web browser but it is envisaged there will be a UI made available at some stage. The new Sites.Selected Microsoft Graph permission are also not available for Delegated (as a user) permissions.
I will now show you through a mixture of PnP.PowerShell and PowerShell how to setup an Azure AD app registration and then configure the app with just the new Sites.Selected permission to authenticate to a specific SharePoint site collections. We can then use this app to authenticate using Microsoft Graph to the specific site and access files/make changes to the site etc. Finally we will show what happens when the app tries to access a site collection it does not have permission for.
Guide – Quick Links
- Create Azure AD App with Sites.Selected Permission
- Grant Azure AD App Permission To A Selected SharePoint Site Collection
- Connect with the Azure AD app that has Sites.Selected permission and connect to the specified SharePoint site collection
1. Create Azure AD App with Sites.Selected Permission
We will now use PnP.PowerShell to create using just one command Register-PnPAzureADApp an Azure AD application named SitesResourceSpecific with just Sites.Selected permission. I truly recommend using PnP PowerShell just for this as it makes creating the application and certificate so easy!
Firstly ensure PnP.PowerShell is installed. Then update the below command with your tenant’s details and then run the command. If the username that your run the command under does not have Global Administrator permissions then you will need to get an Global Admin to approve the permission request.
Follow the on-screen prompts to register the Azure AD App i.e. confirm Microsoft Graph permissions and then consent as a Global Administrator.
Then take a note of the AzureAppId and Certificate Thumbprint – you will need these later to authenticate to the app. The Register-PnPAzureADApp command above will automatically install the certificate in your local current user certificate store, the certificate will then be used to authenticate to the app The file path to the certificate in .pfx or .cer format will also be available if you want to access the app from Azure or another computer.
2. Grant Azure AD App Permission To A Selected SharePoint Site Collection
We will now sign into SharePoint using PnP.PowerShell’s Connect-PnPOnline command as a global administrator or as an application with Sites.FullControl.All permissions.
We will then add the Azure AD app to a specific site collection’s permissions using Grant-PnPAzureADAppSitePermission – so the app can access the specified site collection. See the command below where I am giving the App write permissions to the site https://tenantname.sharepoint.com/sites/sitesselected:
You will see below when I ran the command that permission was applied successfully for write permission to the SitesResourceSpecific app on the specified site collection.
This is where PnP.PowerShell excels as if I wanted to do the same command with pure MS Graph (Create Site Permission) I’d need to know the ID of the Site Collection (see example below) or beforehand make an additional calls to MS Graph to retrieve the site ID.
Whereas PnP.PowerShell allows me to specify the url of the site to add the permission using Grant-PnPAzureADAppSitePermission and I dont need to know the site id at all!
You can use the following PnP.PowerShell commands to further administrate Azure AD App Site permissions:
- Get-PnPAzureADAppSitePermission to retrieve the Azure AD App permissions permissions for a site.
- MS Graph Equivalent – Get Site Permission
- Remove-PnPAzureADAppSitePermission to revoke a permissions for a app to a site.
- MS Graph Equivalent – Delete Site Permission
- Set-PnPAzureADAppSitePermission to change the permission of an app on a site i.e. change from Write to Read.
- MS Graph Equivalent – Update Site Permission
3. Connect with the Azure AD app that has Sites.Selected permission and connect to the specified SharePoint site collection
Now we have added the Azure AD app to the permissions for the site collection (/sites/SitesSelected) I will now show you how to connect to your app and then connect to the site. Finally we will try and connect to another site and we should see that we get the error message “Access Denied”
Unfortunately the native SharePoint APIs (CSOM & SPO REST) which are used by most of the PnP.PowerShell cmdlets at the moment do not handle the Sites.Selected permissions at the moment. Only calls to the Graph work with Sites.Selected permissions at the moment so most PnP.PowerShell commands i.e. Get-PnPList wont work as behind the scenes it uses CSOM and REST.
So for this example we will be using pure Microsoft Graph commands using PowerShell and will not be using any PnP.PowerShell.
Generate Microsoft Graph Access Token with Certificate
I am now going to show you how to generate an access token using a application and certificate. I could not have done it any better so I am using Adam The Automators script from here.
Change lines 2, 3 & 4 to reflect your tenant name, AppId and certificate thumbprint which we made a note of when we created the app using Register-PnPAzureADApp. Finally run the script and if there are no errors then the access token should have been created successfully and be available in the $request variable.
If you return the $request variable by typing in $request you should see that an Access token has been created. We will then use this Access token for future graph requests (note the access token does expire so if you have a long session you will need to run the above script again to generate a new access token).
Connect to site collection where the app has been added to the site permissions
We will now connect to the site collection /sites/siteselected using the code block below and show that we can connect to the site using PowerShell and get the site information.
If you are successful we should get the below reported to the console. Take a note of the SiteId (the middle ID in the id section with a red rectangle around it).
We will now use this Site Id in another Graph query to show the lists in the /Sites/SitesSelected site collection. Update line 1 to reflect the SiteId you just obtained.
If the above commands run successfully you should see the list information of your site collection.
We could then use the Site Id and List Id we just obtained from the previous calls to update a list in the site collection using the below Microsoft Graph commands.
Try to connect to a site collection where the App has not been granted permissions
I will now show you what happens if you try to connect to a site where you have not been granted Sites.Selected permissions to and it will show that access is denied. Change line 1 on the commands below to a site that you know you don’t have Sites.Selected permissions applied.
When you run the commands below you should see that you are given a big red error message with “Access denied. You do not have permission to perform this action or access this resource.”
So the resource specific/sites selected permissions have worked and I only have access to the site collection /Sites/Selected and no other sites!
Sites.Selected/Resource Specific permissions are a great addition in Microsoft Graph to allow permission to only specified SharePoint site collections rather than ALL. This is the continuation of the work that has recently been done with Microsoft Graph and Microsoft Teams to allow resource specific consent to only certain Teams so applications do not have to be given Group.ReadWrite.All and thus have access to all Microsoft 365 groups.
PnP.PowerShell has made it really easy to create a Azure App secured with a certificate and granted Sites.Selected permissions in Graph. We then used PnP.PowerShell to grant the Azure App write permissions to a site, then we had to switch to pure Microsoft Graph commands in PowerShell using Invoke-RestMethod to access the site, lists, add items etc using Sites.Selected permissions. Unfortunately most PnP.PowerShell cmdlets at the moment do not use Microsoft Graph and instead use CSOM or SPO rest which is not supported for Sites.Selected permissions at the present time.
So we have to write more lines of code i.e. pure Microsoft Graph commands to administrate the SharePoint site collection rather than use the lovely PnP PowerShell cmdlets to administer the site. I believe it is in the roadmap in the future to switch more PnP PowerShell cmdlets over to Microsoft Graph but there are still some differences between what can be done in Graph vs CSOM vs SPO REST. At the moment in SharePoint you can generally do more from an API level with CSOM and SPO REST than Microsoft Graph.
I hope this blog article and code samples is helpful for you and helps your organisation. Please let me know in the comments below if you have any feedback, questions or are using it in your organisation?