Lesson 2 of 12 · 15 min read
Access-Control Models: RBAC, ABAC and ReBAC in Depth
In this lesson
TL;DR: Every authorization model answers the same question: may this subject perform this action on this resource, in this context? RBAC answers through roles: easy to review, but it explodes when roles start encoding individual objects, tenants or conditions. ABAC evaluates attributes of the subject, resource and environment: expressive, but it is hard to answer "who can see this?", and attribute data becomes security-critical. ReBAC follows relationships such as owner, group member and parent folder; Google's Zanzibar does this for more than 2 trillion relationships at millions of checks per second. Real systems combine all three. The hard engineering is elsewhere: deny semantics that differ between engines, filtering lists of results, stale permissions after revocation, and agents that must get the intersection of their own rights and the user's, never the union.
Before you read
Pick an answer before you read further. The lesson below explains it, and guessing first, right or wrong, helps the explanation stay with you.
1A company has a role called 'editor-project-falcon', another called 'editor-project-osprey', and 600 more like them. What has gone wrong, and what model fits better?
One question, four inputs
Authentication versus authorization introduced the split between a policy enforcement point (PEP), which intercepts the request, and a policy decision point (PDP), which decides. This lesson is about what happens inside the decision.
Every model takes four inputs:
- Subject: who is asking. A user, a service, or an agent acting for a user.
- Action: read, edit, approve, delete, call a tool.
- Resource: the document, account, payment or model.
- Context: time, device, network, risk score, the purpose of the request.
The models differ in which inputs they use and how. Two older ideas still shape the vocabulary. In discretionary access control (DAC), the owner of an object decides who may access it, as in file permissions and sharing links. In mandatory access control (MAC), a central authority decides and users cannot change it, as with military classification. The classic MAC model, Bell-LaPadula, protects confidentiality with "no read up, no write down"; its dual, Biba, protects integrity with the reverse. Today's models are mostly ways to make DAC and MAC manageable at scale.
RBAC: roles as the unit of permission
Role-based access control puts roles between users and permissions. Users get roles; roles get permissions. It was formalised by Ferraiolo and Kuhn at NIST in 1992 and standardised as ANSI INCITS 359 in 2004. The standard has four components, and interviewers like candidates who know them:
- Core RBAC: users, roles, permissions and sessions.
- Hierarchical RBAC: roles inherit from other roles, so a senior role includes a junior one.
- Static separation of duty: some role pairs can never be assigned to the same user. Nobody may hold both "create payment" and "approve payment".
- Dynamic separation of duty: a user may hold both roles, but cannot activate both in the same session.
RBAC's great strength is review. "Who can approve payments?" is a lookup: list the members of the roles that carry that permission. Auditors love it for that reason.
Kubernetes RBAC is a useful modern example. Permissions are purely additive: there are no deny rules. Roles apply in one namespace and cluster roles everywhere, and a role binding can grant a cluster role inside one namespace only. It also blocks a classic escalation: you can only create a role containing permissions you already hold (or with the escalate verb), and you can only bind a role whose permissions you hold (or with the bind verb). A developer allowed to create role bindings in their namespace still cannot grant themselves cluster-admin.
- 1
1 · Core RBAC
users, roles, permissions, sessions
- Users get roles
- Roles get permissions
The foundation
- 2
2 · Role hierarchy
senior roles inherit junior ones
- Manager includes analyst
- Fewer assignments to maintain
Inheritance
- 3
3 · Static separation of duty
conflicting roles never assigned together
- Create and approve payment
- Checked at assignment
Fraud control
- 4
4 · Dynamic separation of duty
conflicting roles never active together
- May hold both roles
- Cannot use both in one session
Flexible control
Indirection
Permissions attach to roles, so access changes with a job, not with each user.
Role explosion, and why it happens
NIST's ABAC guide (SP 800-162) describes the failure precisely: RBAC does not easily support decisions that depend on several factors, such as location or recent training, and implementing them "would require the creation of numerous roles that are ad hoc and limited in membership", which is what people call role explosion. Kuhn, Coyne and Weil (IEEE Computer, 2010) put a bound on it: with n yes-or-no attributes there are 2^n combinations, so encoding them in roles can need up to 2^n roles in the worst case.
Three patterns cause almost all of it:
- Per-object roles.
editor-project-falconis a relationship pretending to be a role. The role count grows with the number of objects, not with job functions. - Per-tenant roles. In a multi-tenant product,
acme-adminandglobex-adminare copies of the same role. OWASP's authorization guidance notes RBAC is poorly suited when distinct customers need access to the same set of resources. - Context as roles.
analyst-eu-office-hoursturns a condition into a role.
Worked example: counting roles
A company grants access by department, region and seniority: 12 departments × 8 regions × 4 levels = 384 roles, before a single project or customer exception. Add three data classifications and it becomes 384 × 3 = 1,152. Kuhn's worst case for 10 independent attributes is 2^10 = 1,024 roles.
The same policy as one attribute rule:
allow if subject.department == resource.department
and subject.region == resource.region
and subject.level >= resource.minimum_level
One rule, three attributes, and nothing to add when a region opens. The cost moves elsewhere, as the next section shows.
Encode every combination as a role
12 departments × 8 regions × 4 levels
384 roles, 1,152 with classifications
grows with every new value
Every new region adds 48 roles
Outcome, unsafe: Unmanageable
Reviews drown, and one wrong assignment hides among hundreds.
Evaluate attributes in one rule
Subject and resource carry attributes
One rule compares them
department, region, level
New region needs no policy change
Outcome, safe: Compact
The risk moves to the accuracy and freshness of the attribute data.
Multiplication
Roles multiply because each combination of conditions needs its own role.
ABAC: attributes and a decision engine
Attribute-based access control evaluates rules over attributes of the subject, the resource, the action and the environment (time, location, threat level). NIST SP 800-162 describes four functions, and the names are standard interview vocabulary:
- PEP enforces decisions where the request arrives.
- PDP computes the decision by evaluating policy.
- PIP supplies attributes: the HR system, the device manager, the data catalogue.
- PAP is where policies are written, tested and managed.
ABAC has two weaknesses that strong candidates name without prompting.
Review is hard. NIST's comparison of policy systems (SP 800-178) says formula-based systems such as XACML "cannot do either type of review efficiently": neither "what can this user access?" nor "who can access this object?". With RBAC you list role members; with ABAC you would have to evaluate the rules against every subject.
Attributes become part of the security boundary. If anyone can edit their own department in the HR system, or the data catalogue mislabels a dataset, the policy is perfectly enforced and completely wrong. Treat each attribute source as security-critical: who can write it, how fresh it is, what happens when it is missing.
The common answer is a hybrid. Kuhn's 2010 paper describes a "role-centric" variant in which attributes can only reduce what a role grants, never expand it. You keep RBAC's ability to compute anyone's maximum permissions, and use attributes for context.
PEP
intercepts the request
PDP
evaluates policy
PIP
HR, device, data catalogue
Decision
permit or deny, logged
PAP
where policies are written, tested and versioned
Enforcement and decision are separate
The application asks; a policy engine decides.
ReBAC: relationships and Google's Zanzibar
Relationship-based access control decides from a graph: Alice is an owner of this document; this document's parent is that folder; the folder's viewers include the engineering group; Carol is a member of that group. Sharing and inheritance, which explode RBAC, are natural here. OWASP's authorization guidance recommends preferring attribute- and relationship-based control over pure RBAC.
Google's Zanzibar paper (USENIX ATC 2019) made the model concrete. Permissions are stored as relation tuples of the form object#relation@user, where the user can itself be a set, such as all members of a group:
group:eng#member@alice
group:eng#member@group:eng-leads#member
group:eng-leads#member@carol
folder:specs#viewer@group:eng#member
doc:roadmap#parent@folder:specs
doc:roadmap#owner@dave
A configuration for each object type defines how relations combine, using three building blocks: the tuples stored directly, another relation on the same object ("every editor is also a viewer"), and a relation followed to another object ("viewers of the parent folder are viewers of this document"). These combine with union, intersection and exclusion.
Worked example: tracing one check
Can Carol view doc:roadmap? The document type says: viewer = direct viewers ∪ editors ∪ viewers of the parent.
- No tuple makes Carol a direct viewer of the document.
- Editors include owners, and the owner is Dave, not Carol.
- The parent is
folder:specs. Evaluate its viewers: the members ofgroup:eng. group:engcontains Alice directly and every member ofgroup:eng-leads, which contains Carol. Allow.
To block one contractor despite group membership, add an exclusion: viewer = (all of the above) minus blocked. Exclusion is ReBAC's equivalent of an explicit deny.
doc:roadmap
no direct grant to Carol
Parent folder
folder:specs viewers
group:eng
includes eng-leads
group:eng-leads
Carol is a member
Nothing direct
The document has no tuple naming Carol, and she is not the owner.
Scale, and the "new enemy" problem
The paper reports more than 2 trillion relation tuples occupying close to 100 TB, more than 10 million client queries per second, a 95th-percentile latency under 10 ms, and availability above 99.999% over three years, serving Drive, Calendar, Cloud, Maps, Photos and YouTube. Availability matters that much because if the authorization service is down, every product must deny access.
The paper's most important idea for interviews is the new enemy problem. Alice removes Bob from a folder, then asks Charlie to put a new document in it. If the check for Bob's access to the new document reads a stale copy of the permissions, from before his removal, Bob sees a document created after he lost access. A cache or a lagging replica produces exactly this.
Zanzibar's answer is the zookie: when content is saved, the application gets an opaque token encoding a point in time later than every permission change so far, and stores it with the content. Later checks on that content must be evaluated at a snapshot at least that fresh. Most checks can still be served quickly from replicated data, because "at least as fresh as this content" is usually satisfied already. The open-source descendants keep the idea: SpiceDB calls the token a ZedToken, while OpenFGA offers per-request consistency modes instead.
Zanzibar also builds a specialised index, Leopard, for deeply nested groups. It flattens membership so that "is Carol in this group?" becomes an intersection of two precomputed sets.
Alice
Folder owner
Docs app
Stores content
Authz service
Relationship store
Bob
Just removed
- Changes
Alice to Authz service
1Alice to Docs app
2
Order matters
The removal happened before the new content existed. The check must respect that order.
Combining policies: who wins?
Most real decisions combine several policies, and engines disagree about how. This is where many production bugs live.
| System | Default | When policies conflict |
|---|---|---|
| AWS IAM | Deny | An explicit deny anywhere wins. Identity and resource policies in one account combine as a union; permission boundaries, service control policies and resource control policies intersect with them, and SCPs never grant anything. |
| Cedar (AWS Verified Permissions) | Deny | A matching forbid always overrides a permit. A policy that errors during evaluation is skipped, including a forbid. |
| Kubernetes RBAC | Deny | No deny rules exist; permissions only add up. |
| Google Cloud IAM conditions | Deny | A conditional role binding does not override an unconditional binding for the same role; separate deny policies exist for blocking. |
| XACML | Set by policy | Explicit combining algorithms: deny-overrides, permit-overrides, first-applicable, only-one-applicable. |
| Zanzibar-style ReBAC | Deny | Allowed only if a relationship path exists; exclusion subtracts. |
Two traps from that table come up repeatedly:
- Cedar's skip-on-error. Cedar chose to skip erroring policies so that one broken policy cannot deny every request. The consequence: a
forbidthat reads an attribute some resources lack errors on those resources, gets skipped, and a matchingpermitallows access. Validate policies against a schema (Cedar's validator is designed so validated policies cannot error this way), guard optional attributes withhas, and alert on evaluation errors. - Adding a condition does not remove a grant. In Google Cloud, a new conditional binding does nothing if the same role is also granted unconditionally. The same shape appears everywhere: a narrow rule added beside a broad one.
Policy engines compared
| Cedar | Open Policy Agent (Rego) | OpenFGA and SpiceDB | |
|---|---|---|---|
| Model | Permit and forbid policies over principal, action, resource and context | General rules over JSON input | Relationship tuples and a schema, with conditions for attributes |
| Where data lives | Passed with each request | Request input plus pushed data bundles | The engine stores relationships as the source of truth |
| Analysis | Schema validator; an SMT-based analyser can prove two policy sets equivalent; the core is formalised in Lean | Unit tests; partial evaluation | Schema checks; expand and lookup answer "who can" and "what can" |
| Listing what a user can see | Not built in | Partial evaluation can produce a database filter | ListObjects and LookupResources |
| Status (November 2026) | Open source since 2023; managed as Amazon Verified Permissions | CNCF graduated project since 2021 | OpenFGA is a CNCF incubating project; SpiceDB is open source from Authzed |
The OpenID Foundation approved AuthZEN Authorization API 1.0 as a final specification in January 2026. It standardises the call from enforcement point to decision point: a JSON request with subject, action, resource and context, and a decision of true or false, plus batch evaluation and search endpoints. It lets you swap decision engines without rewriting every enforcement point.
Where enforcement lives, and the list problem
A gateway can check coarse things: is the caller authenticated, which tenant, which route. Only the service knows the specific object, and only the data layer can scope a query that returns many objects. OWASP's rule is to check access on every request for the specific object being accessed.
The hardest everyday case is the list: "show me every document I can see" across 50 million documents. Checking each one is far too slow. The established options:
- Search, then check. Query and rank in your own database, then batch-check the top results. Simple, but you may need to fetch more candidates than you show, because some will be filtered out.
- Ask the engine for the list first. OpenFGA's ListObjects or SpiceDB's LookupResources returns the IDs a user can access, which you then pass into the query. This works well up to thousands of results; SpiceDB's own documentation warns it gets heavy beyond about 10,000.
- Keep a local permission index. Consume the engine's change feed into your own database, filter with it, and re-check the final page against the engine to catch revocations not yet indexed.
With policy engines like OPA, partial evaluation turns a policy into a residual condition that can be translated into a database filter.
Revocation latency is the cost of every cache: the time until a removed permission stops working is the largest of your cache lifetime, replication lag and index sync delay. Know that number, and for sensitive actions, check against the source of truth at the moment of use.
- 1
1 · Search, then check
rank in your database, batch-check the page
- Simple to build
- May return fewer results than asked for
Good when most items are visible
- 2
2 · List from the engine first
ListObjects or LookupResources
- Exact and fresh
- Heavy beyond thousands of results
Good when few items are visible
- 3
3 · Local permission index
change feed into your database
- Fast at large scale
- Re-check the final page
Good at Drive-like scale
Filter after
Fine when a user can see most things, and the page is small.
Authorization for RAG and agents
AI systems inherit whatever access model sits under their data, and they make its flaws visible.
Assistants search what people can already reach. Microsoft states that Microsoft 365 Copilot only surfaces organisational data that the user has at least view permission for, and it publishes guidance on reducing oversharing before deployment. The assistant enforces the model correctly. The leak comes from documents that were shared with "everyone" years ago and never found, until a search engine that reads everything made them easy to find. Clean up sharing before you launch an assistant.
RAG needs the same model at retrieval time. When documents come from Drive, Confluence or SharePoint, both the text and the permissions are copied: text into a vector index, permissions into a relationship store or index metadata. That copy lags. Treat index-time permission metadata as an optimisation, not the decision: filter with it, then re-check the final top results against the source of truth before the text reaches the model. The re-check is cheap because only a handful of chunks survive. RAG security covers the retrieval side.
Agents get the intersection, never the union. An agent acting for Alice must be allowed only what both Alice may do and the agent or task is granted. In a relationship model that is an intersection rule, or two checks that must both pass; in AWS terms it behaves like a session policy. Auth0's FGA guidance models agents as principals and recommends task-based grants: the agent starts with nothing and receives only what a task requires, with expiry or call limits. Tools themselves become resources with a can_call relation. Delegated authorization for agents covers how the tokens carry this.
Agent uses its own broad grant
Alice asks the agent to summarise her team's files
Agent's service account can read every team
agent rights stand in for Alice's
Injected instruction asks for HR files
Outcome, unsafe: Over-reach
Alice gets content she could never open herself.
User rights ∩ task rights
Same request from Alice
Check Alice may read, and the task may read
both must allow
HR files fail Alice's check
Outcome, safe: Bounded
The agent can never exceed the user it serves or the task it was given.
The confused deputy
A broad service identity turns any instruction the agent reads into the agent's authority.
When the model was missing
| Case | What happened | The model failure |
|---|---|---|
| First American Financial, 2019 | About 885 million title documents were reachable by changing a sequential number in a link, with no login, according to KrebsOnSecurity. The SEC later settled with the company over disclosure controls, noting staff had found the flaw months earlier. | Holding a link was treated as permission; no relationship between requester and document was checked. |
| USPS Informed Visibility API, 2018 | Any logged-in user could view account details of about 60 million others, and the API accepted wildcard searches. | Authentication without object or tenant scoping. |
| Peloton, 2021 | Researchers found user data available without authentication despite a private-profile setting; the first fix still exposed it to any logged-in user. | A privacy attribute existed but no rule evaluated it. |
| Optus, 2022 | The Australian regulator ACMA alleges a coding error from 2018 left access controls ineffective on one API domain, fixed on the main domain but not that one. These are allegations in court proceedings. | Enforcement fixed in one place and not another, the argument for a shared decision point. |
OWASP's Top 10 keeps broken access control at number one in 2025 and reports that every application in its test data had some form of it. Note the wording if you quote it: the 2021 edition said 94% of applications were tested for it, not that 94% were vulnerable.
Misconceptions interviewers listen for
- "ABAC replaces RBAC." Most designs are hybrids, often with roles as one attribute and attributes only narrowing what roles grant.
- "ABAC is easier to audit." It is harder: answering "who can access this?" means evaluating rules for everyone.
- "ReBAC is for social networks." Zanzibar serves Cloud, Calendar, Maps and YouTube.
- "Every engine has deny rules." Kubernetes RBAC has none, and a conditional binding in Google Cloud does not cancel an unconditional one.
- "Policy errors fail closed." Cedar skips erroring policies, forbids included.
- "Permission caches are safe because permissions rarely change." Revocation is exactly when stale data hurts.
- "The AI assistant leaked the data." Usually it surfaced data that the permission model already allowed.
What if · interview follow-ups
Hold your answer as the constraints change
You are designing authorization for a multi-tenant document platform with folders, sharing, enterprise admins and an AI assistant that answers questions over a customer's documents. The interviewer pushes on model choice and failure modes.
Start here
Which access-control model do you choose, and for what?
Different questions need different models.
A hybrid. Roles for coarse duties such as tenant admin and billing, because they are easy to review. Relationships for documents, folders, groups and sharing, because inheritance and per-object grants would explode as roles. Attributes for context, such as device posture, data classification and region, applied as conditions that can only narrow what roles and relationships grant. One decision service evaluates all three.
Carry it forwardRoles for duties, relationships for objects, attributes for context.
Weak answerPicking one model for everything.
Constraint changes
A user is removed from a folder, then a new document is added there. A cached check lets them read it. What is this, and how do you fix it?
Zanzibar named it.
The new enemy problem: a check using permissions from before the removal grants access to content created after it. Store a consistency token with each content version and require checks at least as fresh as that token, and use fully consistent checks for revocation-sensitive actions. Bound cache lifetimes and publish a revocation latency target.
Carry it forwardTie content versions to a point in the permission history.
Weak answerTurning off caching everywhere, which does not scale.
Constraint changes
The search page must show every document a user can see among 50 million. How do you authorize it?
Three patterns, chosen by selectivity.
Not by checking each document. If users see a small set, ask the engine for the list of IDs first and pass it into the query. If they see most things, search then batch-check the page, over-fetching to fill it. At Drive-like scale, keep a local permission index from the change feed and re-check the final page against the engine to catch recent revocations.
Carry it forwardPick list filtering by how much a typical user can see, and re-check what you show.
Weak answerFiltering results only in the user interface.
Constraint changes
A Cedar forbid policy for 'restricted' documents reads an attribute some documents lack. What happens?
How does Cedar treat errors?
On documents without the attribute, the forbid errors and Cedar skips it, so a matching permit allows access. Validate policies against a schema so this cannot pass review, guard optional attributes with has, make the attribute mandatory for the resource type, and alert on evaluation errors returned with each decision.
Carry it forwardSkip-on-error means an erroring forbid is no forbid.
Weak answerAssuming policy errors deny.
Constraint changes
An auditor asks who can read the payroll folder. How do you answer in each model?
Which model makes this easy?
With roles, list members of the roles that grant it. With relationships, expand the folder's viewer relation through groups and inheritance, which engines such as Zanzibar's expand or SpiceDB's subject lookup provide. With attributes, you must evaluate the rule for every subject, which is why NIST notes formula-based policies are hard to review. Prefer designs where this question has a direct answer.
Carry it forwardReviewability is a design requirement, not an afterthought.
Weak answerSaying you would grep the policy files.
Constraint changes
The AI assistant summarises documents for a user. What authorization does retrieval need?
The index is a copy.
The same model as the documents. Index-time permission metadata lags behind the source system, so filter with it for speed, then re-check the final retrieved chunks against the decision service before they reach the model. Propagate deletions and revocations from the change feed, and clean up broad sharing before launch, because the assistant will surface anything the user can technically reach.
Carry it forwardFilter for speed, re-check for correctness, and fix oversharing first.
Weak answerTrusting a nightly ACL sync as the decision.
Constraint changes
The assistant can also take actions through tools. What does it get to do?
Union or intersection?
The intersection of what the user may do and what the task or agent is granted, never the agent's own broad rights. Model tools as resources with a can_call relation, start agents with no permissions and grant per task with expiry, and require both a user check and a task check on every tool call. Log both decisions so an investigator can see who authorised what.
Carry it forwardAn agent never exceeds the user or the task.
Weak answerGiving the agent a service account that can do everything any user can.
Now defend it
As the defender, what do you monitor once this is live?
Decision logs with inputs and results; denials and errors by policy, especially evaluation errors; revocation latency measured end to end; growth in roles and in documents shared with everyone; attribute changes in source systems that alter many decisions; agent tool calls where the user check and task check disagree; and re-check failures in RAG, which reveal stale index permissions.
Primary references
References for the mechanisms discussed above, accessed 6 November 2026:
- NIST SP 800-162: Guide to Attribute Based Access Control and NIST SP 800-178: comparison of XACML and NGAC.
- NIST role-based access control project and its FAQ on the RBAC standard's components.
- Kuhn, Coyne and Weil, "Adding Attributes to Role-Based Access Control", IEEE Computer, 2010.
- Pang et al., "Zanzibar: Google's Consistent, Global Authorization System", USENIX ATC 2019.
- Cedar authorization semantics and Cutler et al., "Cedar: A New Language for Expressive, Fast, Safe, and Analyzable Authorization".
- AWS IAM policy evaluation logic and Kubernetes RBAC.
- OpenFGA: search with permissions, SpiceDB consistency and OPA decision logs.
- OpenID AuthZEN Authorization API 1.0.
- OWASP Authorization Cheat Sheet and OWASP Top 10 2025, A01.
- Microsoft 365 Copilot data privacy and permissions and Auth0 FGA: RAG authorization.
- Incidents: KrebsOnSecurity on First American, the SEC settlement, KrebsOnSecurity on USPS and Pen Test Partners on Peloton.
How this shows up in interviews
Expect "RBAC versus ABAC versus ReBAC?", "what is role explosion?", "how would you build Google Drive's sharing model?", "how do you authorize search results?" and, in AI roles, "how should a RAG system or agent enforce permissions?". Strong answers choose a hybrid with reasons, trace a relationship check, explain the new enemy problem and consistency tokens, know how their engine combines allow and deny, and give agents the intersection of user and task rights.
Say it in 30 seconds: "All three models answer whether a subject may do an action on a resource in a context. Roles are easy to review but explode when they encode objects or conditions; attributes are expressive but hard to audit and make attribute sources security-critical; relationships handle sharing and inheritance, as in Zanzibar. I use roles for duties, relationships for objects and attributes to narrow by context, behind one decision service. Then I handle the hard parts: deny semantics in my engine, list filtering, consistency after revocation, re-checking RAG results, and giving agents user rights intersected with task rights."
Check yourself
Say or write your answer first, then reveal. Explaining it from memory, in your own words, is the skill an interviewer is checking.
1What is the difference between static and dynamic separation of duty in RBAC?
2What are the PEP, PDP, PIP and PAP in ABAC?
3What is the new enemy problem?
4Why can an erroring forbid policy in Cedar lead to access being allowed?
5What permissions should an agent acting for a user have?