April 27, 2026

How to Lock Down SharePoint Access with Sites.Selected Permissions

Introduction

If you've ever granted an app Sites.ReadWrite.All permissions in SharePoint, you know that sinking feeling you've just given it the keys to every single site in your tenant. For most applications, that's like using a sledgehammer to hang a picture frame.

There's a better way: Sites.Selected permissions. This feature lets you grant your application access to only the specific SharePoint sites it actually needs nothing more, nothing less. It's the principle of least privilege in action, and it's surprisingly straightforward to set up.

In this guide, I'll walk you through the complete process of configuring Sites.Selected with read-only access to a specific SharePoint site. We'll use Microsoft Graph Explorer (no PowerShell required), and by the end, you'll have a secure, properly scoped application that can only access the data it needs.

What Is Sites.Selected and Why Should You Care?

Sites.Selected is a Microsoft Graph permission that flips the traditional access model on its head. Instead of granting tenant-wide access upfront, you start with zero access and explicitly grant permissions to individual sites as needed.

Think of it this way:

  • Sites.ReadWrite.All = Master key to every door in the building
  • Sites.Selected = Specific key cards for only the rooms you need

This approach drastically reduces your attack surface. If your application's credentials are ever compromised, the blast radius is limited to just the sites you've explicitly granted access to not your entire SharePoint environment.

The Three-Phase Process

Setting up Sites.Selected permissions involves three distinct phases, each building on the last:

Phase Action Where
1 Create app registration & add Sites.Selected permission Azure Portal
2 Get SharePoint site ID Microsoft Graph Explorer
3 Grant read permission to site Microsoft Graph Explorer

Here's the crucial thing to understand: after Phase 1, your app has Sites.Selected consent but zero actual access. It's not until Phase 3 that you grant permission to specific sites. This two-step process is what makes the permission model secure.

What You'll Need

Before we dive in, make sure you have:

  • Global Admin or Application Admin role in Azure AD
  • SharePoint Admin access
  • The URL of the SharePoint site you want to grant access to

That's it. No PowerShell modules to install, no scripts to run just your browser and admin credentials.

Phase 1: Creating Your App Registration

The first phase happens entirely in the Azure Portal. We'll create a new app registration and add the Sites.Selected permission but remember, this doesn't grant access to anything yet.

Navigate to App Registrations

Head to https://portal.azure.com and sign in with your admin account. Use the search bar at the top to find App registrations and select it.

Register Your Application

Click + New registration and fill in these details:

Field Value
Name SharePoint-Reader-App
Supported account types Accounts in this organizational directory only
Redirect URI Leave blank

Click Register and you'll land on the app overview page.

Save Your Application ID

On the overview page, you'll see an Application (client) ID. This is a GUID that looks something like a3f44e63-e46e-4c31-9213-888c172ca160. Copy this and save it somewhere safe you'll need it in Phase 3.

Add the Sites.Selected Permission

In the left menu, click API permissions, then + Add a permission. Here's where it gets specific:

  1. Select Microsoft Graph
  2. Choose Application permissions (not Delegated this is critical)
  3. Search for Sites.Selected
  4. Check the box and click Add permissions

Application permissions are for background services and daemon apps that run without a signed-in user. Delegated permissions are for apps that act on behalf of a user. For Sites.Selected to work, you must use Application permissions.

Grant Admin Consent

Back on the API permissions page, click Grant admin consent for [Your Organization] and confirm. You'll see a green checkmark appear next to Sites.Selected with a status of Granted.

Important: At this point, your app has Sites.Selected consent, but it still can't access any sites. That's by design. Phase 3 is where you grant the actual site-level permissions.

Phase 2: Getting the SharePoint Site ID

To grant permissions to a specific site, you need its Site ID. This is a long, comma-separated string that uniquely identifies the site in your tenant. We'll use Microsoft Graph Explorer to retrieve it.

Open Graph Explorer and Sign In

Navigate to https://developer.microsoft.com/en-us/graph/graph-explorer and click Sign in to Graph Explorer in the top right. Use your admin account.

Consent to Permissions (Critical Step)

Here's something that trips people up: Graph Explorer needs its own permissions to make API calls. These are separate from your app's permissions.

Click the Modify permissions tab below the query box. Find these two permissions and consent to both:

  • Sites.Read.All (needed to retrieve the site ID)
  • Sites.FullControl.All (needed in Phase 3 to grant permissions)

For each permission, click Consent, then Accept in the pop-up. Verify both show a Consented status before proceeding.

Construct Your Query

Set the method dropdown to GET. Now you need to build the URL. The format is:

https://graph.microsoft.com/v1.0/sites/{tenant}.sharepoint.com:/sites/{sitename}

Let's say your site is https://contoso.sharepoint.com/sites/ProjectAlpha. Your Graph API URL would be:

https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/ProjectAlpha

Note: Use the site name from the URL, not the display name. If your site is called "Project Alpha Site" but the URL is ProjectAlpha, use ProjectAlpha.

Run the Query and Extract the Site ID

Click Run query. In the Response preview, you'll see JSON that looks like this:

{
  "id": "contoso.sharepoint.com,a1b2c3d4-1234-5678-abcd-111122223333,e5f6g7h8-4321-8765-dcba-444455556666",
  "name": "ProjectAlpha",
  "displayName": "Project Alpha",
  "webUrl": "https://contoso.sharepoint.com/sites/ProjectAlpha"
}

Copy the entire id value the whole thing, including the commas. This is your Site ID. Save it alongside your Application ID.

The Site ID format is {hostname},{site-collection-id},{web-id}. Don't try to reconstruct it manually or use just part of it you need the complete string.

Phase 3: Granting Read Permission to Your Site

This is where everything comes together. We'll use a POST request in Graph Explorer to grant your application read access to the specific site.

Set Up the POST Request

In Graph Explorer, change the method to POST. The URL format is:

https://graph.microsoft.com/v1.0/sites/{siteId}/permissions

Replace {siteId} with the full Site ID you copied in Phase 2. For our example:

https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com,a1b2c3d4-1234-5678-abcd-111122223333,e5f6g7h8-4321-8765-dcba-444455556666/permissions

Add the Request Body

Click the Request body tab and enter this JSON:

{
  "roles": ["read"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "YOUR-APPLICATION-CLIENT-ID",
        "displayName": "SharePoint-Reader-App"
      }
    }
  ]
}

Critical: Replace YOUR-APPLICATION-CLIENT-ID with the Application ID you saved in Phase 1. Using our example ID, the complete JSON would be:

{
  "roles": ["read"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "a3f44e63-e46e-4c31-9213-888c172ca160",
        "displayName": "SharePoint-Reader-App"
      }
    }
  ]
}

The roles array specifies the permission level. We're using read for read-only access. Other options include write, manage, and fullcontrol.

Execute and Verify

Click Run query. If everything is configured correctly, you'll receive a 201 Created response with JSON that looks like:

{
  "id": "aTowaS50fG1zLnNwLmV4dHxlYTVmMDVlZ...",
  "roles": ["read"],
  "grantedToIdentitiesV2": [...],
  "grantedToIdentities": [...]
}

That id field in the response is the permission ID. Save it if you think you might need to update or revoke this permission later.

Verifying Everything Works

To confirm the permission was granted successfully, you can query the permissions endpoint. Change the method back to GET and use:

https://graph.microsoft.com/v1.0/sites/{siteId}/permissions

Click Run query. You should see your application listed in the response with roles set to ["read"].

Understanding Available Permission Roles

We used read in this guide, but Sites.Selected supports four permission levels:

Role Description
read Read-only access (used in this guide)
write Read and write access
manage Manage lists and libraries
fullcontrol Full control over the site

Choose the most restrictive role that meets your application's needs. If you only need to read documents, stick with read.

Common Issues and How to Fix Them

Here are the most common problems people run into and their solutions:

403 Forbidden Error

If you get a 403 error when trying to grant permissions in Phase 3, you likely haven't consented to Sites.FullControl.All in Graph Explorer. Go back to the Modify permissions tab and consent to it.

Site Not Found

Double-check that you're using the site name from the URL, not the display name. If your site URL is /sites/proj-alpha but the display name is Project Alpha Team Site, use proj-alpha.

Insufficient Privileges

Make sure you've clicked Modify permissions in Graph Explorer and consented to both Sites.Read.All and Sites.FullControl.All. These are Graph Explorer's permissions, not your app's.

Invalid Request Body

Check your JSON syntax carefully. Common mistakes include missing commas, mismatched brackets, or forgetting to replace YOUR-APPLICATION-CLIENT-ID with your actual Application ID.

Wrapping Up

Sites.Selected permissions represent a massive improvement in security posture for SharePoint integrations. Instead of granting blanket access to your entire tenant, you can scope applications down to exactly what they need and nothing more.

The process involves three phases: creating an app registration with Sites.Selected consent in Azure Portal, retrieving the Site ID using Graph Explorer, and granting site-specific permissions via a POST request. Each phase builds on the last, and by the end, you have a properly scoped application that follows the principle of least privilege.

If you're building SharePoint integrations, this should be your default approach.

If you have any questions you can reach out our SharePoint Consulting team here.

No comments:

Post a Comment