
A RAG system does not know what it is not supposed to tell someone. It only knows what is semantically close to the question. If your knowledge base mixes a public wiki with HR files, legal contracts, or support tickets containing customer PII, that is not a retrieval quality problem to tune later. It is an access control decision you need to make before ingestion starts.
Why this is a buyer decision, not an engineering detail
Search results can already expose sensitive titles or snippets when authorization is missing. RAG adds another exposure path: retrieved text becomes material for a generated answer. A polished response may reveal information without showing the user the document that supplied it. For a buyer, the useful question is therefore not just whether the answer is relevant. It is whether every piece of context was permitted for this requester before it reached the model.
Treat authorization as part of the retrieval contract. The system needs to carry the authenticated requester, the document identity, and the applicable policy through the query. A source application denying access is not enough if a separately indexed copy is available through the assistant. Decide how that copy will be protected before extending the pilot to departments with different access rights.
The core tradeoff: pre-filter, post-filter, or separate indices
Three useful patterns are authorization-aware retrieval, filtering retrieved candidates before generation, and separate indices. These can be combined; the choice depends on the permission model, the database, and the components allowed to handle restricted content.
Pre-retrieval filtering applies authorization at query time, before the vector similarity search runs. The database only ever returns chunks the requesting user is entitled to see. Supabase's documented pattern is a concrete example: because pgvector sits on top of Postgres, you can implement row level security on the vector table itself, restricting which documents are returned during a similarity search to users who have access to them. If the permission data doesn't live in the same database, Postgres foreign data wrappers can pull it from an external system.
RAG with Permissions - Supabase
Database enforcement can centralize the policy, but it is not an automatic performance guarantee. Benchmark with realistic group sizes, restrictive policies, and your chosen vector index. Check the role actually executing the query: a privileged backend connection may bypass policies that worked in a user-session demo. The permission model must also stay synchronized with the source systems. If permissions live across Drive ACLs, Confluence spaces, and a custom entitlements table, someone must define how each maps to the policy evaluated at retrieval time.
Post-retrieval filtering fetches candidate matches, then checks their authorization before any rejected content reaches generation or another component outside the permitted boundary. Auth0 demonstrates this with a custom retriever that checks vector-search results against Auth0 FGA. OpenFGA can support both pre-filtering and post-filtering; adopting it does not force one ordering. The design decision is where the check runs and which components can see the unfiltered candidates.
Secure Java AI Agents: Authorization for RAG Using LangChain4j and Auth0 FGA
An authorization service can make policy reusable across applications. The costs to measure include extra checks, network latency, and the number of relevant candidates left after filtering. If the first ten matches are unauthorized, returning an empty answer does not prove the corpus has no useful authorized material. Define bounded retrieval expansion or a suitable pre-filter and test relevance under restrictive permissions. Ensure every retrieval path invokes the check, and decide how requests fail when the authorization service is unavailable.
Securing Agentic/RAG Pipelines with Fine-Grained Authorization
Separate indices per tenant or sensitivity tier can make the access boundary easier to inspect. They do not automatically provide physical isolation: several indices may share infrastructure, credentials, and application routing. A service able to query all of them still needs an enforced rule for selecting the permitted index. This design also adds ingestion and lifecycle work when documents serve multiple audiences. Use it when the operational separation fits the access model, and test routing, credentials, and deletion across the boundary rather than assuming separate names prove isolation.
Prerequisites checklist before ingestion starts
Each pattern needs usable permission data. Start with a bounded corpus whose owners and access rules are known. Agree which gaps prevent ingestion and which can be addressed within that smaller scope. Expanding to an unclassified enterprise-wide corpus should be a separate decision with its own acceptance checks.
- Is there an existing source-of-truth for who can see each document (SSO groups, Drive or Confluence ACLs, a custom entitlements table)? If not, this has to be built first; it is not something a RAG pipeline can solve after the fact.
- Does identity propagate end-to-end from the chat interface to the actual retrieval call, not just to the application login screen?
- Is there a plan for chunk-level sensitivity? Splitting a permissioned document into smaller pieces does not automatically carry the permission along with each piece.
- Is there a process for permission changes, such as someone leaving a team or a document being reclassified, to invalidate or re-filter content that has already been indexed?
Chunks need stable links back to the documents and policy records that authorize them. If preprocessing discards that mapping, permission changes become difficult to apply reliably. Preserve source identifiers through ingestion and re-indexing, and test how document deletion removes derived chunks. Background jobs need their own least-privilege service identities; they should not be confused with the end user whose rights govern a query. Both paths need explicit access boundaries, although they serve different purposes.
Failure cases worth naming explicitly
A few patterns show up repeatedly in RAG deployments that didn't scope access control up front. Naming them concretely helps during a design review, because they are easy to miss in an architecture diagram that only shows the happy path.
- A single shared index with no filtering at all, where retrieval relevance scoring, not authorization, is what actually determines what the model sees and surfaces to the user.
- Permission checks implemented only in the UI layer, which get silently bypassed the moment someone calls the API directly or an agent invokes the retrieval tool without going through the chat frontend.
- Chunking pipelines that drop source-document metadata during preprocessing, which makes later permission enforcement impossible without a full re-ingestion of the corpus.
The common thread across all three is that access control got treated as a UI concern or a later cleanup task rather than a property of the data model itself. Once the index exists without permission metadata, retrofitting it is not a configuration change, it is a data migration.
A decision checklist for scoping conversations
Before committing to an architecture, a buyer should be able to answer these questions with confidence. If the answer is 'we don't know yet,' that's a signal the project isn't ready for ingestion.
- Does your source data have more than one sensitivity tier or intended audience? If yes, you need filtering of some kind, not a single shared index with no restrictions.
- Can your current identity system express a statement like 'document X is visible to group Y' today? If not, that is a prerequisite project in its own right, not a feature you add to the RAG pipeline later.
- Is your permission model flat, based on simple roles, or relational, with nested teams, shared documents, and dynamic project-based access? Flat roles tend to fit row-level security well; relational models usually need a dedicated authorization layer.
- Who owns re-syncing permissions when they change in the source system, after the initial build is handed over?
Assign an owner and a propagation target for permission changes. People change teams, contractors leave, and documents move between audiences. A permission snapshot taken at ingestion can become stale. Decide whether each query checks current policy, relies on synchronized metadata, or combines both, then measure the delay when access is revoked. Include caches and saved conversations in that review: blocking a new retrieval does not automatically remove an answer already stored elsewhere.
Test the service account, revocation, and failure paths
A pilot run through one broadly privileged service account cannot establish that ordinary users receive only authorized answers. Keep that as an explicit limitation of the demo. Before widening access, run a small acceptance exercise with synthetic documents, two test users, and deliberately different permissions. The following is a proposed test plan, not a report of a client deployment.
- Create one shared document and one restricted document containing distinctive synthetic facts. Give only the first user access to the restricted document.
- Ask both users questions that would retrieve the restricted fact. Inspect the context supplied to the model as well as the final answer. A model declining to repeat a fact does not prove retrieval was authorized.
- Revoke the first user’s permission and repeat the query. Measure the propagation delay against the agreed target, including permission caches and indexed metadata.
- Remove the identity or tenant context, then simulate an authorization timeout. Confirm the system denies access to protected material rather than falling back to the ingestion service account.
- Exercise direct API requests and agent retrieval tools in addition to the chat interface. Verify they use the same policy boundary.
Record the test identities, document IDs, policy version, expected decisions, and observed results without copying confidential document contents into a general-purpose log. Decide who may inspect traces that contain candidate chunks. An external reranker, tracing service, or cache can create another disclosure path even when the final prompt is filtered. Place the authorization check before any component that is not permitted to process those candidates.
The result should be evidence the receiving team can repeat after a policy or retrieval change. Include both allowed and denied queries, because a system that blocks every request is not a successful implementation either. If the exercise exposes a gap, reduce the corpus or stop the affected path while the team fixes it. Do not turn a missing permission record into a default allow merely to improve the answer rate.
OpenFGA: RAG authorization patterns
Scoping this honestly
A useful rollout plan identifies the requester, protects every retrieved chunk, and tests denial paths as carefully as successful answers. Agree on acceptance evidence for the actual corpus and access model, and retain an owner who can update that evidence as policies change. A smaller, explicitly authorized corpus is a practical starting point while the organization resolves wider data-governance gaps.