DEV Community

Cover image for Read access to one SharePoint site needs FullControl first: how our AI indexer handles it
Kaspars Jurjāns
Kaspars Jurjāns

Posted on

Read access to one SharePoint site needs FullControl first: how our AI indexer handles it

The easy way to let an AI assistant read SharePoint is one consent: the Microsoft Graph application permission Sites.Read.All. Microsoft describes it in one line: "Allows the app to read documents and list items in all site collections without a signed in user." The setup finishes, the crawler never meets a closed site, and nobody keeps a list of sites.

The narrow way is Sites.Selected. It has one awkward step, and this post is about that step.

Sites.Selected starts at zero

Selected scopes "require an explicit assignment action", so an app that has only been consented "would initially have no access." Three things must be true before the indexer can read a site:

  1. The app is consented for Sites.Selected in Entra ID.
  2. The site is granted to that app with a role, through POST /sites/{siteId}/permissions.
  3. The token the app presents carries the scope.

Miss one and "the application doesn't have access." An indexer needs the read role and nothing more: "Read the metadata and contents of the resource."

The awkward step

Creating the site grant needs a very large key. The call requires Sites.FullControl.All, and Microsoft explains why: "Because you can grant full control permissions to a site collection by using Sites.Selected, this requirement is necessarily high."

So to give one app read access to a few sites, something must hold full control for a moment. This is what our installation script does with that moment:

  • It creates a temporary app with Sites.FullControl.All and uses it only to make the grants.
  • It posts one grant per chosen site:
POST /sites/{siteId}/permissions
{
  "roles": ["read"],
  "grantedToIdentities": [
    { "application": { "id": "<indexer app id>", "displayName": "Answergrove Indexer" } }
  ]
}
Enter fullscreen mode Exit fullscreen mode
  • It removes the temporary app's permission and secret, so that even a restored copy could do nothing.
  • It deletes the app and then removes it from the deleted items. Microsoft keeps a deleted application restorable "for up to 30 days", and after a permanent delete it "cannot be restored."
  • If any cleanup step fails, it stops with an error, names what is left and does not count the installation as finished.

The order matters. Take the permission away first and delete second, so that a failed permanent delete leaves only an empty shell in the recycle bin.

Two identities, one rule

The indexer runs on a schedule with nobody signed in. The part that answers people never holds the indexer's credential. Microsoft notes that application-only scenarios "have no user present and are considered higher risk", while with delegated access "the application can never exceed the current user's existing permissions."

For the indexer that means three things:

  • A certificate, not a client secret. The token request carries client_assertion instead of client_secret.
  • The private key in Azure Key Vault, where "key usage is logged in near real time."
  • A guard in the answering API. In our build the API refuses to start, with exit code 78, if indexer credential settings are present where it runs.

Test the denial, not the grant

A grant that works proves little. The useful test is the opposite one: with the indexer's own credential, request the drive of a site you never granted. The expected result is an access error, not a file listing.

Our script ends with that test and records the result before anything is indexed. The test proves the state of the tenant at the minute it ran, so it has to be repeated after every change to the site list or the app registrations.

One thing we have not measured: Microsoft states "Application access is lost as soon as a scope is revoked," but we do not know how quickly that holds for a token issued just before the revocation.

The full article covers the Entra admin center checks and lists every Microsoft source: Before an AI Reads Your SharePoint: Which Permissions Its Indexer Really Needs. The product this script installs is Answergrove.

Top comments (0)