Installation

Configure-SharePoint-Access

Modified on Mon, 28 Sep at 2:06 PM

Table of contents


Introduction


This page describes how to give an application access to specific SharePoint sites only, instead of the whole sharepoint, using the Sites.Selected permission.


Assign the Sites.Selected permission


Prerequisites

  • Consent. Adding Sites.Selected as an application permission on Microsoft Graph can only be consented to by Global Administrator or Privileged Role Administrator. 


What to do

  1. Go to Entra ID → App registrations → your app → API permissions, and select Add a permission.
  2. Choose Microsoft Graph. The list also offers a SharePoint entry — do not use it. Both clients call Graph and nothing else.
  3. Choose the permission type that matches your client. Do this before looking for the permission— the portal filters the list by type, so searching first will not find it.
    • Delegated permissions — for a desktop client



    • Application permissions — for an autonomous client


  4. Under Select permissions, search for and tick Sites.Selected, then select Add permissions.
  5. If one registration serves both clients, which is the usual case, you end up with two Sites.Selected rows under Microsoft Graph — one Delegated, one Application.
  6. Select Grant admin consent for <your tenant>, then Yes in the confirmation dialog.


How to check it worked


Select Refresh — the Status column often does not update on its own — and check that every row you added reads Granted for <your tenant> with a green tick. 


If Grant admin consent is greyed out, or consenting fails, your account does not have the authority for it. You need a Global Administrator.


The screenshots also show openid, profile, offline_access and User.Read. Those come with the registration and can be left alone — only Sites.Selected has to be added by hand.


Grant the app access to specific SharePoint sites


These steps use the Microsoft Entra admin center at https://entra.microsoft.com, where the section is called Entra ID. The same pages exist in the Azure portal under Microsoft Entra ID — either works.


In the commands, everything in {curly-braces} is a placeholder you must replace with your own value. The table under Values you need covers the ones you gather up front and the ones you obtain along the way.

Prerequisites

  • To setup you should have SharePoint Administrator or higher" role with Sites.FullControl.All  scope.
  • The URL of every SharePoint site you intend to grant, for example https://contoso.sharepoint.com/sites/ProjectDocs.


Values you need


The first four you can gather before you start. The next three you obtain as you work through this step


PlaceholderWhat it isWhere to get itExample
{client-id}Application (client) ID of the app registration that needs SharePoint accessAzure portal → Entra ID → App registrations → your app → Overview → Application (client) ID. Not the Object ID, and not the enterprise application (service principal) object ID.11111111-2222-3333-4444-555555555555
{app-display-name}Friendly name of that same app. Stored next to the grant so permission listings are readable.Same Overview page → Display nameILAP Flow Client
{sharepoint-hostname}Your SharePoint Online hostEverything between https:// and the next / in any site URLcontoso.sharepoint.com
{site-name}Name of the target siteThe part of the site URL after /sites/. If your site URL uses /teams/ instead, use that in the path too. ProjectDocs, from https://contoso.sharepoint.com/sites/ProjectDocs
{access-token}OAuth 2.0 bearer token for Microsoft Graph, belonging to the administrator performing this setup. Only needed if you send the requests yourself, from a tool like Postman — Graph Explorer supplies its own.Graph Explorer → Access token tab. Usually valid 60–90 minutes.eyJ0eXAiOiJKV1QiLCJhbGciOi... (~1500 characters)
{site-id}Graph's composite ID for the site — hostname,siteCollectionId,webId. It is not the site URL.Returned by the call herecontoso.sharepoint.com,9e7f0a1b-1234-4c9d-b6f1-aaaaaaaaaaaa,4dc44a2e-5678-4e11-9f22-bbbbbbbbbbbb
{permission-id}ID of a grant created here, needed to change or revoke it laterThe id field in the POST responseaTowaS50fG1zLnNwLmV4dHw...


Check your permission


Check your permission using the official Graph Explorer


  1. Open https://developer.microsoft.com/graph/graph-explorer.
  2. Sign in as a Global Administrator, or another role that can grant tenant-wide admin consent. That account also has to hold SharePoint Administrator or higher.
  3. Click the profile avatar (top right) and choose Consent to permissions. That screen lists every available permission. Search for Sites.FullControl.All and consent to it, ticking Consent on behalf of your organization in the prompt. (There is also a Modify permissions tab below the address bar, but it only lists permissions needed by whatever query is currently in the address bar — so Sites.FullControl.All will not appear there until you have pasted one of the calls from this step. It is also still in preview. The profile avatar is the reliable route.)
  4. Choose the verb (GET / POST), paste the URL, put the JSON in the Request body tab, and click Run query.


To confirm the token carries the right permission, paste it at https://jwt.ms and look for Sites.FullControl.All in the scp claim.


Find the site ID


First, work out which site you are granting

You will usually be handed the address of the library or folder the files are going into, not the site — because that is the address that goes into SchedEx. Permission, though, is granted on the site. So trim it back first.


This step gives you {sharepoint-hostname} and {site-name}


What you were given{sharepoint-hostname}{site-name}
https://contoso.sharepoint.com/sites/ProjectDocscontoso.sharepoint.comProjectDocs
https://contoso.sharepoint.com/sites/ProjectDocs/Shared%20Documents/Archivecontoso.sharepoint.comProjectDocs
https://contoso.sharepoint.com/teams/Projects/Reports/Q1contoso.sharepoint.comProjects — note this one sits under /teams/, not /sites/
https://contoso.sharepoint.com/sites/ProjectDocs/Forms/AllItems.aspx?id=...contoso.sharepoint.comProjectDocs
https://contoso.sharepoint.com/Invoices/Q1 — no /sites/ or /teams/ partcontoso.sharepoint.comnone — this is the tenant root site


The rule: keep the host plus /sites/<name> or /teams/<name>, and drop everything after it. If there is no /sites/ or /teams/ part at all, the site is the host on its own.


One grant on that site covers every library and folder inside it, so you do not repeat this per folder.


Granting the root site is broader than granting an ordinary site — know what you are agreeing to.


An address with no /sites/ or /teams/ part means the tenant's root site collection, usually the organisation's intranet home page. A grant there covers every document library on that root site, and cannot be narrowed to one of them.

Then ask Graph for its ID

The site ID is not the site URL. Ask Graph for it by path:


GET https://graph.microsoft.com/v1.0/sites/{sharepoint-hostname}:/sites/{site-name}?$select=id,name,webUrl
Authorization: Bearer {access-token}


Worked example for https://contoso.sharepoint.com/sites/ProjectDocs:


GET https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/ProjectDocs?$select=id,name,webUrl


$select is part of the URL, not a variable. 


Response:


{
  "id": "contoso.sharepoint.com,9e7f0a1b-1234-4c9d-b6f1-aaaaaaaaaaaa,4dc44a2e-5678-4e11-9f22-bbbbbbbbbbbb",
  "name": "ProjectDocs",
  "webUrl": "https://contoso.sharepoint.com/sites/ProjectDocs"
}


Use that whole id value, commas included, as your {site-id}.

Special  cases:


  • For the tenant root site, the call above does not work — there is no /sites/<name>to put after the colon. Ask for it by name instead:
    GET https://graph.microsoft.com/v1.0/sites/root

    This is the case whenever the address has no /sites/ or /teams/ part — for example a library at https://contoso.sharepoint.com/Invoices.

    Everything else is unchanged: the id it returns is your {site-id}, the role in Decide the role is still write, the POST in Grant the permissionis identical, and one grant covers every library on the root site.

  • If the site URL uses /teams/ rather than /sites/, put that after the colon:
    GET https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/teams/Projects

    The two /sites/ in the earlier example are not the same thing, which is easy to misread. The first one is Graph's own collection and never changes. Everything after {sharepoint-hostname}: is your site's real path, copied from its URL — so a /teams/ site produces the shape above, with only one /sites/ in it.
  • For a subsite, do not grant it separately. Grants are made on the site collection and reach subsites by inheritance, and Graph refuses a subsite grant outright.
  • For Microsoft Teams, see If your files live in Microsoft Teams at the end of this subsection — some channels are their own site and some are not.


If your files live in Microsoft Teams


SharePoint has no concept of a "channel". Team channels simply become a site there, and those are the ones that need a grant of their own.


In TeamsIn SharePointGrant
The team itselfone sitegrant it
A standard channeljust a folder in that team's default document libraryalready covered by the team's grant — do not look for a separate site
A private channelits own separate siteneeds its own grant
A shared channelits own separate siteneeds its own grant


Do not expect a Teams site to be under /teams/. A team's site commonly sits under /sites/, the same as any other — https://contoso.sharepoint.com/sites/Delivery. The /teams/ path only appears in tenants configured to use it. Both work here; go by the address you actually see, not by the fact that it came from Teams.


A private or shared channel's site sits beside the parent team's site rather than inside it — something like .../sites/Delivery-Finance next to .../sites/Delivery. As far as SharePoint is concerned those are two unrelated site collections that happen to have similar names, which is exactly why a grant on the parent does not reach the channel. Resolve the ID with the call above rather than building that URL yourself; Microsoft does not document the naming as a contract.


Decide the role

RoleWhat the app can do
readRead files, folders and list items
writeRead, plus create, update and delete files and folders
manageWrite, plus manage the site's lists and settings
ownerFull control of the site's content, as the site's owner
fullcontrolEverything the site's content allows, including permissions on its lists, folders and files. It does not extend to handing out access to the site itself, which needs the separate Sites.FullControl.All described here.


Grant the lowest role that works. Storage at home writes files and creates folders, so write is what it needs — and so do the Excel, Microsoft Project and P6 XER File connectors, which write as well as read.


Microsoft's own pages are inconsistent about this list: its permissions reference gives read/write/owner/fullcontrol, while manage appears in its announcement and in PnP PowerShell. It does not affect you — write is on every version of the list.


Grant the permission


Replace placeholders with your values, then paste the raw HTTP block into Graph Explorer. Then run request.


POST https://graph.microsoft.com/v1.0/sites/{site-id}/permissions
Authorization: Bearer {access-token}
Content-Type: application/json

{
  "roles": ["write"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "{client-id}",
        "displayName": "{app-display-name}"
      }
    }
  ]
}


Keep the response. It contains the grant's own id — that is {permission-id}, and you need it to change the role or revoke access later.


{
  "id": "aTowaS50fG1zLnNwLmV4dHwxMTExMTExMS0yMjIy...",
  "@deprecated.GrantedToIdentities": "GrantedToIdentities has been deprecated. Refer to GrantedToIdentitiesV2",
  "roles": ["write"],
  "grantedToIdentities": [
    { "application": { "id": "11111111-2222-3333-4444-555555555555", "displayName": "ILAP Flow Client" } }
  ],
  "grantedToIdentitiesV2": [
    { "application": { "id": "11111111-2222-3333-4444-555555555555", "displayName": "ILAP Flow Client" } }
  ]
}


The response carries the grant twice. Read grantedToIdentitiesV2 when inspecting a listing — grantedToIdentities is deprecated on the way out. The request body still uses grantedToIdentities; that has not changed.


A grant may not take effect the moment it is created. Microsoft does not document a propagation time, so wait few minutes.

Changing or removing a grant later


You can change the role if you need later:


PATCH https://graph.microsoft.com/v1.0/sites/{site-id}/permissions/{permission-id}
Authorization: Bearer {access-token}
Content-Type: application/json

{ "roles": ["read"]
}


You can also revoke access:


DELETE https://graph.microsoft.com/v1.0/sites/{site-id}/permissions/{permission-id}
Authorization: Bearer {access-token}

Give the person access in SharePoint


This is applicable for the desktop client only


The desktop client works on behalf of the person signed in, and can never do more than that person could do by hand. So the previous step only half the job — the person needs access to the folder as well.

What to do

Open the site in a browser, click the Settings gear, and choose Site permissions.


What you see next depends on the kind of site, and you do not need to know in advance — the buttons tell you.


  • A team site — one with a Microsoft 365 group behind it, which is what a site from Teams has. You see an Add members button. It opens a menu of two. Choose Share site only, enter the person's name, set the level to Edit, and select Add. The other option, Add members to group, also works but hands over more than the site — the group's mailbox, calendar and Teams team come with it.
  • A communication site, or any site with no Microsoft 365 group. You see Share site instead, and no menu. Enter the person's name, set the level to Edit, and select Add.


If your tenant has not picked up Microsoft's newer labels, the button reads Invite people rather than Add members. It is the same button and the menu under it is the same.


The level dropdown offers only Read, Edit and Full control. Choose Edit. Do not choose Read — it lets them open files but not add any, so transfers fail. (Contribute would also be enough, but it is not on this menu and you do not need it.)

Two cases where that is not enough

  • The folder is in a Teams private or shared channel. SharePoint shows a channel site's permissions read-only, so the steps above will not work — it has to be done in Teams. Go to the channel name → More options (the ... beside it) → Manage channel → the Members tab, and add the person there.
    For a private channel the person must already be in the parent team before you can add them to the channel. Being in the team is not enough on its own — you still have to add them to the channel. For a shared channel they do not need to be in the team at all.
  • The library has its own separate list of who may use it. Someone set that library up with its own permissions, so access given on the site never reaches it. Open the library → Settings gear → Library settings. You may then need to select More library settings. On that page, under Permissions and Management, choose Permissions for this document library, then Grant Permissions.
    If Grant Permissions is not there, the library is still inheriting from the site after all — so this was not the problem. Go back and check the site permissions instead.


The second one is easy to miss. Suspect it whenever the person's site access looks right and uploads still fail.

How to check it worked


Ask the person to open the folder in a browser and upload any file to it by hand.


If they cannot, the desktop client cannot either. Fix their access before looking anywhere else.


If they can, this step is done. That does not on its own mean the transfer will work: the application still needs its own grant from this step. Both halves have to be in place.


That is also the quickest thing to check if a transfer works from the autonomous client but fails from the desktop one — the site grant is not the problem, that person's own access is.


Which SharePoint addresses the product accepts


This part is about configuring the product, not about granting permission. It is here because the two are usually done in the same sitting, and because the address you configure decides which site you had to grant above.


How to copy the address


Open the document library or folder in SharePoint in a browser, and copy the address out of the browser's address bar. That is the only method that reliably produces something the product can read.


If the files live in a Microsoft Teams channel, you have to get to the browser first. In Teams, open the channel, select the Shared tab, then More commands (the ... in the command bar) → Open in SharePoint. That opens the same library in a browser, and the address bar then holds the address you want. Note that this tab used to be called Files and much of Microsoft's own documentation still says so.


Do not use Share → Copy link. Those links carry a permission token rather than a path — there is nothing in them that says where the folder is, so they are rejected. It is the most common way to get this wrong; Why a sharing link is refused shows the two side by side.


Do not hand-type an address either. Spaces, accented characters and the like have to be encoded exactly as the browser encodes them, and a hand-typed address that looks right often is not.


A copied address is usually much longer than the folder path, because SharePoint appends the state of the page you were looking at. That is expected — the product trims it to the part that names the location and stores only that, which is why the address you see after saving is shorter than the one you pasted.

Addresses that work

What you pasteWhat it means
https://contoso.sharepoint.com/sites/ProjectDocsthe site — data goes to its default document library, which is the behaviour every existing setup has
https://contoso.sharepoint.com/teams/Projectsthe same, for a tenant that puts sites under /teams/
https://contoso.sharepoint.coma tenant whose site collection is the host root
.../sites/ProjectDocs/Invoicesa named document library
.../sites/ProjectDocs/Invoices/Q1a folder inside a library, at any depth
https://contoso.sharepoint.com/Invoicesa named library on the root site, where the address has no /sites/ part
https://contoso.sharepoint.com/Invoices/Q1a folder inside it — the same shapes work with or without /sites/
.../sites/ProjectDocs/Shared Documents/Archivethe folder Archive in the site's default library — Shared Documents and Documents both name the default library and are read as that, not as a library of their own. This is the shape most existing setups already hold
.../sites/ProjectDocs/Invoices/Forms/AllItems.aspxthe same library — the view-page tail is trimmed off
.../Forms/AllItems.aspx?id=%2Fsites%2FProjectDocs%2FInvoices%2FQ1the folder named in the address bar while you were looking at it
.../AllItems.aspx?RootFolder=%2Fsites%2F...the same, in the older form some tenants still produce
a subsite addresstreated like any other site path


The folder must already exist. The product creates only its own sub-folders inside what you point at. A folder that is not there is an error naming it, rather than something silently created.


An address that names a file is accepted, not rejected — the folder holding the file is used. Where you paste one on a settings screen you are asked first and can keep what you typed, because a folder is allowed to have a file-like name. The question is raised whenever the last part of the address contains a dot, so a folder genuinely called Rev.2 is asked about too. Only SharePoint can tell the two apart, which is why you are asked rather than corrected.

Addresses that are refused, and what to do instead

What you pasteWhat you are told
Anything not starting https://Enter a complete address starting with https://
An address whose host does not end .sharepoint.com — SharePoint Server on-premises, or a mistyped hostThat address is not on SharePoint Online. Paste an address from your own organisation's SharePoint
A Share → Copy link URLOpen the folder in SharePoint and copy the address from the browser address bar
A OneDrive address (-my.sharepoint.com), or a /personal/ sitePaste a SharePoint document library or folder instead
A SharePoint admin centre address (-admin.sharepoint.com)Paste a document library or folder instead
A settings page — anything containing _layouts, including Office-for-web document linksThat is a settings page, not a library or folder
A list — .../Lists/Budgets/...Lists cannot store files; paste a document library or folder
Any other page ending .aspxOpen the folder and copy the address from the browser address bar
One of SharePoint's own libraries — Style Library, FormServerTemplates, SiteAssets, SitePages, PreservationHoldLibrary, Teams Wiki DataChoose a document library created for content
An address containing #Everything from the first # onwards never reaches SharePoint, so the address is truncated. Copy it again from the address bar


For Storage at Home there is also a length limit of 512 characters, applied to the trimmed address rather than the one you pasted, so an ordinary browser copy is never too long on its own. The file connectors have no length check.

Compare a Share → Copy link link with the address bar for the same folder:


https://contoso.sharepoint.com/:f:/g/EQx7Kd2mVfBHrN4pLcWt9YkBa1TqZs6RmXvD3hJnPwGeUA https://contoso.sharepoint.com/Invoices/Forms/AllItems.aspx?id=%2FInvoices%2FQ1


The second spells the folder out. The first does not contain it at all — that token is a record that someone may open something, not a location, and it can be revoked or expire. So there is nothing to store, which is why sharing links are refused rather than resolved.


Open the folder in SharePoint and copy the address from the browser's address bar instead.


The one thing this page cannot check for you

Nothing at save time confirms that the site, library or folder actually exists, or that the application has been granted the site. A convincing typo saves cleanly and only shows itself when a transfer runs or the connector's test button is pressed. If the address names a different site collection from the ones you granted above — a Teams private channel is the usual way this happens — it saves without complaint and then fails at transfer time with a permission error. Grant every site collection you intend to use.

References



Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article