RAG and access control: making a RAG inherit Active Directory (Entra ID) permissions
A RAG inherits Active Directory permissions by propagating the user's group membership to the search filter, on three levels: an ACL tag at ingestion, a pre-retrieval filter at query time, a check at response time. An Entra ID / Microsoft Graph tutorial, the six cases that break it (nested groups, token overflow, revocation), and the IAM/RBAC generalisation. For architects, lead engineers and mid-market CTOs.
Transparency note. This article follows the IgnitionAI editorial policy. Claims about the behaviour of Entra ID, Microsoft Graph and SharePoint link to the official Microsoft Learn documentation, with an access date. The architecture recommendations are IgnitionAI estimates, tagged as such.
A few weeks after an internal assistant goes live, an operator in a business unit asks a routine question. The answer quotes a briefing note for the compensation committee, which they should never have seen. The assistant forced nothing: it queried the index while honouring technical permissions far broader than the business owners believed. This is the scenario we see most often on engagements, and it is fixed at design time, not after the incident.
An enterprise RAG inherits Active Directory permissions by propagating the user's group membership to the search engine. This happens on three levels: an ACL tag set on each chunk at ingestion, a pre-retrieval filter applied at query time, a check at response time. Here is how to wire it on Entra ID, and the six cases that break it in production.
The mental model: from identity to chunk
The principle is a chain. The user is authenticated by Entra ID. Their security-group membership travels to the vector store, which only returns chunks whose permissions overlap those groups.
User (Entra ID)
-> security groups (token claims, or Microsoft Graph on overflow)
-> pre-retrieval filter on the vector store
-> chunks whose ACL tags overlap the user's groups
-> LLM generation over that authorised subset only
The golden rule: no out-of-scope document should enter the context passed to the LLM. Filtering the generated answer afterwards is too late, the model has already read the document. Filtering happens before the similarity search, what we called pre-retrieval in our comparison of five access-control architectures. This article digs into the concrete implementation of one of them.
Step 1 · Tag chunks at ingestion
Each indexed chunk carries the permissions of its source document. At ingestion time, you read the document's permissions (SharePoint security groups, file-system ACLs) and store them as chunk metadata.
{
"text": "Q4 financial close procedure, step 3...",
"acl": ["grp-finance-fr", "grp-direction"],
"source": "sharepoint/finance/close-q4.docx",
"sensitivity": "confidential",
"version": "2026-06-01"
}The acl field holds the identifiers of the groups allowed to read the document. The sensitivity and version fields serve compliance control and targeted deletion (see below). Without this metadata set at ingestion, no clean filtering is possible later.
Step 2 · Resolve the user's groups at query time
On every query, you retrieve the authenticated user's groups, then pass them as a filter predicate to the vector store.
Microsoft Graph exposes a user's transitive membership, nested groups included, through the transitiveMemberOf API (Microsoft Graph documentation, accessed June 2026):
GET https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.group?$select=idYou then pass the resulting list to the vector store. On Qdrant, the metadata filter (Qdrant filtering documentation, accessed June 2026) takes the form of an "at least one group in common" match:
{
"filter": {
"must": [
{ "key": "acl", "match": { "any": ["grp-finance-fr", "grp-direction", "grp-all"] } }
]
}
}The similarity search then applies only to chunks whose acl contains at least one of the user's groups. The rest of the index stays invisible.
The six cases that break in production
This is where most implementations go wrong. Each of these cases is documented, and each has a fix.
1. Nested groups. If a user belongs to GroupB, and GroupB belongs to GroupA, their rights include both. Direct membership is therefore not enough: you need transitive membership. Entra ID group claims include nested groups, unless you restrict claims to groups assigned to the application (Microsoft Entra, group claims, accessed June 2026). Use transitiveMemberOf, never direct membership alone.
2. The token overflows. Entra ID limits the number of groups emitted in a token: 150 for a SAML assertion, 200 for a JWT. Beyond that, the groups are simply omitted from the token (same source). An implementation that reads groups from the token will then give incomplete results to your most connected users. The fix: for those accounts, query Microsoft Graph rather than trusting the token.
3. The 1,000-group filtering limit. Entra ID supports group filtering only if the user belongs to 1,000 groups or fewer, direct and transitive memberships combined (same source). Beyond that, the architecture must switch to another authorisation model, for example application roles rather than raw groups.
4. Revocation and reindexing latency. Removing a user from a group takes effect immediately if you resolve their groups on every query. However, if a document is reclassified or has its permissions changed, its acl tag in the index stays frozen until reindexing. IgnitionAI estimate based on our 3 engagements in 2024-2025: plan an event-driven incremental reindexing on permission changes, not just a nightly batch, otherwise you face an exposure window of several hours.
5. Deny rules and unique permissions. A document can break inheritance from its site and carry an explicit deny rule, which takes precedence over a group grant. A filter that only reasons in "allowed groups" will let that document through. The ACL tag at ingestion must reflect the document's effective permissions, not those assumed from its location.
6. Disabled accounts and sharing links. A disabled account must lose access immediately, which means invalidating any group cache. And "anyone with the link" sharing links grant access that goes through no group: they are invisible to a membership-based filter. These links must be audited and revoked upstream, not worked around at the RAG level.
Reduce the surface before plugging in the RAG
The opening case of this article doesn't come from the RAG, but from an over-broad permission perimeter inherited from years of sharing. The first action is therefore not technical on the AI side, it is governance on the source side.
Two Microsoft levers exist for this. Restricted SharePoint Search limits organisation-wide search and Copilot to a list of explicitly validated sites, up to 100, turned off by default. It exists precisely to give you time to audit permissions before opening the index (Microsoft, Restricted SharePoint Search, accessed June 2026). Microsoft Purview sensitivity labels classify and encrypt sensitive documents, and that classification propagates to SharePoint and OneDrive (Microsoft Purview, sensitivity labels, accessed June 2026).
The same principle applies to a custom RAG: the index should only ingest sources whose permissions have been audited. A RAG plugged into an unaudited perimeter turns latent oversharing into actionable exposure within days.
Logging and compliance
Access control is only complete with its trace. Every query must log the user, the resolved groups, the returned chunks and the generated answer. This logging meets the traceability obligation of Article 12 of Regulation (EU) 2024/1689 on AI for high-risk systems, and supports an after-the-fact audit.
The right to erasure under Article 17 of the GDPR applies to indexed data. The version field set at ingestion enables targeted deletion of the relevant vectors without full reindexing.
Outside the Microsoft ecosystem
The three-level pattern doesn't depend on Microsoft. With Okta, Keycloak or another identity provider, the principle stays the same: retrieve the user's groups or roles via OIDC or SCIM, tag chunks with the source's permissions, filter at pre-retrieval.
For cases where authorisation depends on attributes rather than groups (region, clearance level, project), the ABAC model replaces group lists with attribute rules. For complex relationships (a user accesses a document because they manage its author), the ReBAC model fits better. The filtering point doesn't change: before the similarity search, never after.
FAQ: RAG and Active Directory permissions
-
How does a RAG inherit Active Directory permissions?
By propagating the user's group membership to the search filter, on three levels. First, an ACL tag set on each chunk at ingestion, namely the source document's allowed groups. Second, a pre-retrieval filter at query time, namely the authenticated user's groups, resolved via Microsoft Graph. Third, a check at response time. No out-of-scope document enters the context passed to the LLM.
-
Should you read groups from the Entra ID token or via Microsoft Graph?
Via Microsoft Graph as soon as the user belongs to many groups. Entra ID limits the token to 150 groups in SAML and 200 in JWT; beyond that, groups are omitted from the token. The Graph
transitiveMemberOfcall returns full membership, nested groups included, without that limit. -
Does group filtering have a limit?
Yes. Entra ID supports group filtering only if the user belongs to 1,000 groups or fewer, direct and transitive memberships combined. Beyond that, you must switch to application roles or an attribute-based authorisation model (ABAC).
-
What happens when you revoke a user's access?
If groups are resolved on every query, revocation takes effect immediately. The trickier case is changing a document's permissions: its ACL tag in the index stays frozen until reindexing. We recommend event-driven incremental reindexing on permission changes, to avoid an exposure window.
Methodology and sources
Technical sources (accessed June 2026):
- Microsoft Graph, List a user's transitive group membership: learn.microsoft.com/graph
- Microsoft Entra, Configure group claims for applications (nested groups, 150/200 and 1,000-group limits): learn.microsoft.com/entra
- Microsoft, Restricted SharePoint Search: learn.microsoft.com/sharepoint
- Microsoft Purview, Sensitivity labels: learn.microsoft.com/purview
- Qdrant, Filtering: qdrant.tech
Regulatory sources:
- Regulation (EU) 2024/1689 on artificial intelligence, Article 12 (logging): EUR-Lex
- Regulation (EU) 2016/679 (GDPR), Article 17 (right to erasure): EUR-Lex
IgnitionAI estimates: the architecture recommendations (incremental reindexing, auditing the perimeter before ingestion) rest on 3 RAG design or audit engagements delivered in 2024-2025 for French mid-market companies in regulated sectors. Possible variation depending on context. See our editorial policy.
Sources last reviewed: 2026-06-14.
Related IgnitionAI articles:
- Access control in an enterprise RAG: 5 architectures compared
- Microsoft 365 Copilot: the governance audit nobody runs
- Enterprise RAG in production: 5 critical decisions your first POCs hide from you
Designing a RAG that must respect your Active Directory access rights? Our two-week scoping covers the perimeter audit, the authorisation model and the target architecture, with a written go/no-go. Request a conversation.