Sites.Selected permissions are required to get access to only a specific SharePoint sites using Microsoft Graph API and/or SharePoint API (since Microsoft announced EOL of SharePoint App-only service principals, Sites.Selected is the only option going forward). Below are
- Brief overview of Sites.Selected
- Step-by-step how to get and configure Sites.Selected permissions
- Secure your app credentials
- Use Sites.Selected permissions
- Govern Sites.Selected permissions
- Automation of Sites.Selected permissions provisioning
- Classic ACS permissions vs modern Sites.Selected permissions
Brief overview of Sites.Selected
Historically, we utilized so called SharePoint app-only service principals to get unattended (daemon/service) access to one specific site programmatically. Initially in on-prem, later in SPO. We used to get SharePoint app-only service principals via appregnew.aspx and provide permissions via appinv.aspx page. SharePoint app-only principals allow calls to SharePoint (REST) API and usage of SharePoint CSOM via ACS-based authentication.
Then Microsoft started developing Graph API. You’d need to register your app in Azure to get App Id and App secret to authenticate to Microsoft Graph API. You’d also configure specific API permissions for this app to get access to services you need (SharePoint, Exchange, Teams etc.). Unfortunately, for a long time there were no options to get access to only one specific site with Graph API. Available API permissions (e.g. Sites.Read.All) allowed access to all SharePoint sites in tenant.
Then, in 2021 Microsoft introduced Graph API “Sites.Selected” application permissions. Hooray! But the problem was devs had to have two service principals – new Sites.Selected to call Graph API and classic SP-App-only to call SharePoint API. Later, in 2022 Microsoft added SharePoint “Sites.Selected” API permissions – so both APIs are available for a single App Id (more App-Only and Sites.Selected history details…).
Long story short, below are the detailed steps to configure Sites.Selected for you unattended app access to SharePoint site.
Steps to get and configure Sites.Selected permissions
1. Register an application in Azure (Entra Id) via Azure portal GUI, PowerShell script or helpdesk/servicedesk request. E.g. with GUI you’d login to portal.azure.com,
then “Entra Id” -> “App registrations” and select “+ New registration”:

With PowerShell you’d do it with e.g. Register-PnPEntraIDApp cmdlet.
If you are not allowed to register an Entra Id app due to restrictions in your company – connect with your IT/admins, as there must me some way to request an app.
Once you get an application registration and you are this app owner – you should be able to navigate to your app registration in Azure Portal and configure it (see Step 2 and below).
2. Update the app “API permissions” – you’d need both – MS Graph API Sites.Selected and SharePoint Sites.Selected application API permissions configured:

Request tenant admin consent for your API permissions. Finally your app registration “API permissions” should look like:

3. App Secret or Certificate
Under Certificates and secrets – generate client secret, copy secret value to safe location.

Or you can get a certificate (obtain trusted or create self-signed), and upload it to your app registration. Certificates are considered as more secure option.
4. At the Overview page – grab your app client id and tenant id :

At this moment, having tenant id, app (client) id and client secret (or certificate) – you should be able to authenticate against Microsoft 365 tenant with app-only authentication path, but should not be able to access any site.
Having just Sites.Selected API permissions configured for app does not mean your app has access to any SharePoint site automatically. Access for the app to a specific site is provided by SharePoint team via another Graph API call. That leads us to the next step.
5. Application access to SharePoint site
You need to request this from your SharePoint service admin (or if you are an admin – DIY), but access needs to be provided for the specific app to the specific site with specified permissions (Read-Only or Read/Write or Manage or Full Control)
– Here is the Graph API
– Here is PowerShell PNP cmdlet
Interesting that MS Graph advertises 3 possible roles – read, write and owner, but PNP team says you can select from 4 roles – Read, Write, Manage or FullControl. Obviously,
- Read role allows an app to read site content;
- Write role is similar to “Contributor” user permissions – it allows CRUD operations against list items (library documents and metadata)
- Manage role allows create/update/delete lists/libraries
- FullControl is full control
At this moment you should be able to access SharePoint sites. How? See below:
Use Sites.Selected permissions
Once your SharePoint tenant/service admin confirmed that access has been provided for you app to specific SharePoint site/sites – you can use app client id and client secret (or certificate) to work with SharePoint from your code using MS Graph API or SharePoint API. Exact technique depends on language/platform you use, but there are some good tutorials published:
- Microsoft’s tutorials on using Graph API with app-only auth (Go, Python, JavaScript etc.)
- PnP team samples of using PnP.Core library to code against Microsoft 365 (.net)
Generally, this Sites.Selected permissions allows you to make calls that are documented under “Files” and “Sites and Lists” Graph API documentation. I.e. get site details, get site lists/libraries, create lists and libraries, CRUD operations against list items, download/upload library documents – all within the specific site. Sites.Selected permissions does not allow search operations, anything related to group or team etc.
If you are facing issues – first of all you’d try to isolate the issue – is it permissions to blame or something else. To ensure permissions for your app were provided correctly – you can validate your app access to the target SharePoint site with simple PowerShell scripts: here is the sample code
Important Note: Sites.Selected API permissions allows you call Microsoft Graph API with client Id and client secret or certificate. Calling SharePoint API with client secret is not supported. You have to use certificate to call SharePoint API.
Calls to SharePoint API with client Id and client secret are possible only if ACS-based permissions are provided for the app to the site (with appinv.aspx), which is strictly not recommended due to announced App-Only (ACS) retirement – see updates in the end of the article.
Secure your credentials
You should not hard-code your secret as you do not want your credentials be leaked. So you need to secure your secrets in production. Solutions for secrets are included in cloud providers offerings, you can also use environment variables. If you are hosting your application in Azure – consider using key vault to keep your secrets. You can configure managed identity for your application and provide access to the key vault for you application managed id. (Actually, if your app is running in Azure – it is possible to provide permissions for your app directly – via managed identity. This is considered as even more secure setup – no app registration and no key vault is needed as there is no credentials to save, but that’s a separate story: Connecting to Microsoft 365 and Graph API from the Azure Function App via Managed Identity).
Govern Sites.Selected permissions
(For SharePoint admins).
Existing admins API/cmdlets allows yo to provide Sites.Selected permissions for specific app to specific site, and to get Sites.Selected permissions provided to the specific site. But there is no API/cmdlet for the specific app to get all sites (with permissions) this app has access to. Meantime as SharePoint admin if you keep providing permissions upon users/devs requests – after some time you have no idea what app has access to what site with what level of access, especially in large organizations. Surely you can (and should) pull reports on all registerd apps with access to SharePoint, but…
There is a solution developed by Joe Rodgers (Microsoft). This solution use SharePoint list as an inventory/storage and Power Automate flows to pull data from Entra Id and SharePoint and provides kind of dashboard so you can review details of all app registrations in the tenant with at SharePoint Online permission. Cool!
Note: you would not provide Sites.Selected permissions just upon user/developer request. You’d always get an approval from target site owner. Target site owner must understand that application will have permanent unattended access to entire SharePoint site with permissions specified (read or write or manage or full control).
Sites.Selected permissions provisioning automation
(for SharePoint admins)
Generally, to provide an Application with Sites.Selected API permissions configured access to a specific site, SharePoint admin would run a set of PowerShell commands (or C# program or…) to ensure the client id exists, API permissions are configured and consented, to get app owners, target site owners, to get existing app permissions etc. Finally, admin would provide permissions and validate that permissions were provided correctly. It does not take long…
But in medium and large environments number of requests could be significant enough to think of automation. I do have a separate article and video on Sites.Selected permissions provisioning automation.
Classic ACS permissions vs Sites.Selected permissions
Note: ACS-based permissions are deprecated:
Your SharePoint admin doesn’t allow site owners to create/update ACS principal ⋆ Vladilen Microsoft 365 engineer
Though Sites.Selected is our choice going forward, old classic ACS-based App-only permissions have some advantages (unique features) Sites.Selected does not have, e.g. ability to provide permissions not to entire site, but to specific list or subsite only. You can get more details checking this article for Comparison between Azure Apps and Entra Id Sites.Selected API permissions vs SharePoint app-only spn and ACS-based permissions.
Update:
Microsoft announced ACS permissions (app-only principals) retirement in 2026. So using ACS for any new development is not recommended.
It may be acceptable to grant ACS permissions to existing legacy custom applications or third-party or Microsoft apps/web apps (e.g. Alteryx, Azure Data Factory) – applications that only support a client ID and secret and use the SharePoint API under the hood – but only to avoid disruption to business processes and keeping in mind that ACS will expire soon, so these applications must be replaced/updated before 2026.
Here is How to prepare your tenant for Azure ACS retirement
Update: Microsoft is implementing granular (permissions to list, item or file) alongside with Sites.Selected permissions. Original implementations of Sites.Selected allowed access to entire site collection only. With new ‘Lists.SelectedOperations.Selected’, ‘ListItems.SelectedOperations.Selected’ and ‘Files.SelectedOperations.Selected’ permissions it is possible to provide application permissions to list, library or list item or particular document (reference).
References
- Using AppRegNew (authenticate) and AppInv (authorize) for SharePoint app-only spns and ACS
- recent update to Microsoft 365 MC660075 that disables for site collection admins to create an Azure Access Control (ACS) principal via AppregNew
- Secret vs Certificate for Connecting to SharePoint Online programmatically
- SharePoint API vs MS Graph API
- how to provide ACS permissions for the application to SharePoint site.
- Dashboard for App Registrations with access to SharePoint
- Connecting to Microsoft 365 and Graph API from the Azure Function App via Managed Identity
- Azure ACS retirement: How to prepare your tenant – Guide for SharePoint Admins