Edit

Share via


Use a SharePoint indexer to ingest permission metadata and filter search results based on user access rights

Note

This feature is currently in public preview. This preview is provided without a service-level agreement and isn't recommended for production workloads. Certain features might not be supported or might have constrained capabilities. For more information, see Supplemental Terms of Use for Microsoft Azure Previews.

This article explains how to ingest an access control list (ACL) alongside other content from SharePoint in Microsoft 365 using an Azure AI Search indexer. Permissions from SharePoint are preserved as permission metadata for each indexed document. When users query an index containing content from SharePoint, their search results consist of only those documents for which they have permission to access.

Architecture diagram showing a security-trimmed RAG solution where a SharePoint indexer ingests documents and ACL permission metadata from a SharePoint site, stores them in an Azure AI Search index, and a RAG orchestrator filters query results so each user retrieves only documents they're authorized to access.

Important

For scenarios that require the full SharePoint permissions model, sensitivity labels, and out-of-the-box security trimming, use a remote SharePoint knowledge source. This approach calls SharePoint directly via the Copilot retrieval API. Governance remains fully in SharePoint, and query results automatically respect all applicable permissions and labels.

Prerequisites

  • Azure AI Search on a billable tier (Basic or higher) in any region.

  • SharePoint in Microsoft 365 sites, libraries, folders, and files with configured permissions.

  • Complete all configuration steps in the SharePoint indexer documentation, applying the ACL-specific requirements described in this article.

  • Configure application permissions with Files.Read.All and Sites.FullControl.All (or Sites.Selected instead of Sites.FullControl.All) to index only the content and permissions of specific sites. Then, grant the application full control permissions for those selected sites.

  • REST API version 2025-11-01-preview or an equivalent preview SDK package.

Limitations

Support for the SharePoint permission model

This preview supports only basic ACLs for documents, as shown in the following table. The SharePoint indexer doesn't support lists ingestion, so it excludes lists permissions.

SharePoint Feature Description Supported Notes
Site & library inheritance Site → library → folder → file. ✔️ Evaluated at ingestion; effective ACLs computed per file.
Folder & file unique ACLs Item-level access. ✔️ Included when present at first ingestion.
Microsoft Entra (M365/Security) Groups Group-based access. ✔️ Group IDs included when resolvable to Entra identifier (ID).
SharePoint site groups Owners/Members/Visitors. ⚠️ Partial Included only when resolvable to Entra group ID.
Shareable "Anyone links" or "People in your organization links" Org-wide or public access. Not supported in preview.
External/guest users Access for guests. Not supported.
Information Management policies Policies to define specific permissions requirements. Not supported in preview.
Purview sensitivity labels Document-level security for privacy, categorization, permissions, and encryption Supported via a separate feature: preserving and honoring sensitivity labels.

How hierarchical permissions are evaluated

SharePoint permissions inherit the hierarchy of Site → Library → Folder → File, unless inheritance is broken.

During ingestion, the indexer gathers user and group identifiers (ID) at each level and computes the effective ACL for each file.

Configure your search service for ACL ingestion and honoring at query time

These steps configure your search service for ACL ingestion and enable ACL honoring at query time.

1. Data source configuration

Set indexerPermissionOptions in the data source definition to allow indexing of userIds and groupIds from SharePoint documents.

{
  "name": "my-sharepoint-acl-datasource",
  "type": "sharepoint",
  "indexerPermissionOptions": ["userIds", "groupIds"],
  "credentials": {
    "connectionString": "<connection-string>;"
  },
  "container": {
    "name": "<library-name>",
    "query": "<optional-folder-path>"
  }
}

2. Add permission fields to the index definition

Add fields to your index schema definition to store ACLs and support query-time filtering.

{
  "fields": [
    { "name": "UserIds",  "type": "Collection(Edm.String)", "permissionFilter": "userIds",  "filterable": true, "retrievable": false },
    { "name": "GroupIds", "type": "Collection(Edm.String)", "permissionFilter": "groupIds", "filterable": true, "retrievable": false }
  ],
  "permissionFilterOption": "enabled"
}

Set retrievable attribute to true only during development to verify values. You can change retrievable from true to false with no index rebuild requirement.

3. Configure index projections in your skillset (if applicable)

If your indexer uses a skillset with data chunking, such as a split skill when enabling integrated vectorization, make sure to map ACL properties to each chunk using index projections.

PUT https://{service}.search.windows.net/skillsets/{skillset}?api-version=2025-11-01-preview
{
  "name": "my-skillset",
  "skills": [
    {
      "@odata.type": "#Microsoft.Skills.Text.SplitSkill",
      "name": "#split",
      "context": "/document",
      "inputs": [{ "name": "text", "source": "/document/content" }],
      "outputs": [{ "name": "textItems", "targetName": "chunks" }]
    }
    // ... (other skills such as embeddings, entity recognition, etc.)
  ],
  "indexProjections": {
    "selectors": [
      {
        "targetIndexName": "chunks-index",
        "parentKeyFieldName": "parentId",          // must exist in target index
        "sourceContext": "/document/chunks/*",     // match your split output path
        "mappings": [
          { "name": "chunkId",           "source": "/document/chunks/*/id" },     // if you create an id per chunk
          { "name": "content",           "source": "/document/chunks/*/text" },   // chunk text
          { "name": "parentId",          "source": "/document/id" },              // parent doc id
          { "name": "UserIds",  "source": "/document/metadata_user_ids" }, // <-- parent → child
          { "name": "GroupIds",  "source": "/document/metadata_group_ids" } // <-- parent → child
        ]
      }
    ],
    "parameters": {
      "projectionMode": "skipIndexingParentDocuments"
    }
  }
}

4. Configure the indexer field mappings for ACLs

Besides your required indexer configuration, map raw metadata ACL fields from SharePoint to your index fields.

{
  "fieldMappings": [
    { "sourceFieldName": "metadata_user_ids",  "targetFieldName": "UserIds" },
    { "sourceFieldName": "metadata_group_ids", "targetFieldName": "GroupIds" }
  ]
}

Synchronize permissions between indexed and source content

During public preview when the configuration is completed, and ACLs are captured during the first indexer run and for new files only. To pick up later changes:

Change Scope Recommended Trigger What refreshes
Single/few files Update LastModified Content and ACLs
Many items Update /resetdocs (preview) with document keys Content and ACLs
Entire site/library (as defined in the data source configuration) Update /resync (preview) with permissions Only ACLs (no content refresh)

Reset specific documents

You can reset specific documents to fully ingest again content and ACLs.

POST https://{service}.search.windows.net/indexers/{indexer}/resetdocs?api-version=2025-11-01-preview
{
  "documentKeys": ["doc123", "doc456"]
}

Resync ACLs across the full data source

You can resync the full data set ACL content after initial ingestion.

POST https://{service}.search.windows.net/indexers/{indexer}/resync?api-version=2025-11-01-preview
{
  "options": ["permissions"]
}

Important

If you change SharePoint permissions without triggering an update mechanism, the index serves stale ACL data for previously ingested files.

After indexing your data and ACLs, you can query the index.