Develop Applications that use Sites.Selected permissions for SPO sites

If you are a developer for SPO, you will find your self in this step where you need to decide sites.selected is enough or you need AllSites.Read, AllSites.FullControl.

🔐 Understanding the Two Permission Models

1. Sites.Selected (Application or Delegated)

This permission allows granular access to specific SharePoint sites. It is explicitly scoped—you must assign access to each site individually using Microsoft Graph API.

  • Application context: Used when no user is present (e.g., background services or daemons).
  • Delegated context: Used when a signed-in user is present, but still scoped to only the selected sites.
  • Roles: Can be read, write, fullcontrol, or manage.

“Sites.Selected is ALWAYS recommended as the preferable, safer alternative option to ANY of the other SharePoint permissions” because it limits exposure to only the sites explicitly granted.

2. AllSites.* (Delegated Permissions)

These permissions (e.g., AllSites.Read, AllSites.FullControl) grant broad access to all SharePoint sites the signed-in user has access to.

  • Delegated only: These permissions are not available in application-only contexts.
  • Risk: They can unintentionally expose more content than intended, especially in non-admin apps.

🔄 How They Interact

When both permission types are present in an app registration:

  • Application permissions (Sites.Selected) take effect only when the app is running without a user context.
  • Delegated permissions (AllSites.**) take effect only when a user is signed in and the app is acting on their behalf.

They do not override each other but rather apply based on the context in which the app is running.

For example, if your app has both Sites.Selected (application) and AllSites.Read (delegated), and a user signs in, the app will have access to all sites the user can access. If no user is signed in, the app can only access the explicitly granted sites [1] [2].

✅ Best Practices

  • Use Sites.Selected wherever possible to follow the principle of least privilege.
  • Avoid combining with AllSites.* unless necessary, and only in delegated scenarios.
  • Always validate access using Graph API or CSOM to ensure permissions are scoped correctly.
Complete scenario to apply sites.selected to retrieve data from SharePoint

The app has sites.full control and we need to restrict the scope using sites.selected

I’ll grant the app to run with only 1 site collection and will perform test using different site collection. I’m using MS graph explorer to perform the scenario and I’ using two site collection “GrantedOne” which the app will be authorized to retrieve data from and “PrivateOne” which the app will not be authorized to.

Steps:

send get request one of theses end points to get the site ID:

Site ID:  copy the site ID from the response

Then send a post request to this end point “https://graph.microsoft.com/beta/sites/{site-ID}/permissions” to give  read permission for the app to GrantedOne site collection

Copy the following the request body

{
   "roles": ["read"],
      "grantedToIdentities": [{
        "application": {
          "id": "app ID",
          "displayName": "app display name"
        }
      }]
    }

  As in the following image:

If you want to validate, you can run a GET request to the same API and you should be able to see the permission was granted to the app

Now let’s test using CSOM code to read the site title. I’ll test using 2 site collections, the granted one and non-granted one

I added the following keys to App.config for easier test

Test 1: using granted site collection

Now, using the generated token to read the site title

The result:

The second test for non- granted site:

The result:

Article introduction:

References

[1] Develop Applications that use Sites.Selected permissions for SPO sites …

[2] Sites.Selected Require Sites.Read.All – Microsoft Q&A