Next-Generation Access Control (NGAC): one graph to express them all

Next-Generation Access Control explained: the NIST standard (INCITS 565, born from the Policy Machine) that models users, attributes, objects, and policies as a single directed graph and computes access as a privilege path through it. How NGAC's assignments, associations, prohibitions, and obligations subsume RBAC, ABAC, and ReBAC under one formal framework, how a decision is derived from the graph, how it differs from XACML, and why its efficient review queries and deterministic evaluation matter even though adoption is still early.

What if one model could express all of them?

The previous five articles each championed a different basis for access: owners, labels, roles, attributes, and relationships. Each was strongest for a shape of problem and clumsy for the others, and real systems ended up combining two or three of them — RBAC for job functions, ABAC for context, ReBAC for sharing — stitched together in application code. That leaves an obvious question hanging over the whole module: is there a single formal structure general enough to express roles, attributes, and relationships all at once, so you do not have to bolt separate engines together? Next-Generation Access Control (NGAC) is the standards community’s answer — an attempt to unify the models rather than add a sixth one.


NGAC’s core bet is radical in its simplicity: model everything as one directed graph. Users, the attributes that group them, objects, the attributes that group them, and the policies themselves all become nodes; the ways they relate become edges. An access decision is then not a rule match or a role lookup but a graph question — does a privilege path exist from this user to this object, granted by an association and not cut by a prohibition? Where ReBAC put relationships between resources in a graph, NGAC puts the entire policy — subjects, objects, attributes, grants, and denials — in one graph, and derives every decision from its structure. That generality is the whole idea, and it is why NGAC is framed not as a competitor to RBAC or ABAC but as a framework in which those models are special cases.


This is the capstone of the model module, and deliberately so. Having seen each basis for access in isolation, you are now equipped to appreciate a model whose selling point is that it contains the others. Whether NGAC becomes the dominant way authorization is built is still an open question — its tooling and adoption trail its ideas — but as a way to understand how roles, attributes, and relationships relate to one another, it is unmatched, and its influence on modern authorization thinking is already deep.


A short history: from the Policy Machine to a standard

NGAC did not appear from nowhere; it is the standardized form of years of NIST research called the Policy Machine, led by David Ferraiolo — the same researcher whose name sits on the original RBAC model from the 1990s. Having helped formalize RBAC, Ferraiolo and colleagues spent the 2000s asking a deeper question: rather than build a new mechanism for each policy type, could there be one general-purpose access-control mechanism whose behavior is entirely determined by configurable data? The Policy Machine was their answer — a machine whose “program” is a graph, so that RBAC, ABAC, multi-level security, and their combinations become different configurations of the same engine rather than different engines.


That research was standardized as NGAC: first as INCITS 499 (2013) and then the revised INCITS 565, with supporting NIST publications (notably the report often cited as NISTIR 7657 on access-control policy combination) fleshing out the model. NIST also ships a reference implementation of the Policy Machine, and a handful of commercial products have adopted the approach. The lineage matters: NGAC comes from the same intellectual tradition as RBAC, extended by two decades of thinking about how to generalize it — which is exactly why it can present roles as one configuration among many.


The elements: everything is a node

NGAC’s vocabulary is small, and learning it is most of learning NGAC. Every policy is built from a handful of element and relation types:


Element / relationSymbolRole in the graph
UserUA subject that makes requests (a person or service)
User AttributeUAA container grouping users (a role, department, clearance, team…)
ObjectOA protected resource (a file, record, endpoint)
Object AttributeOAA container grouping objects (a folder, classification, project…)
OperationopAn action that can be performed (read, write, delete)
Policy ClassPCA named policy the graph belongs to; multiple can coexist
AssignmentPlaces an element into a container (containment edge)
AssociationGrants operations from a UA to an OA (the grant edge)
ProhibitionDenies operations from a user/UA over objects (the deny edge)
ObligationAn event-triggered rule that changes the graph automatically

Three of these edges do the real work, and it is worth being precise about each. An assignment is pure containment: user:sara → UA:engineer says Sara is in the engineer attribute; object:roadmap → OA:research-docs says the roadmap is in the research-docs attribute. Assignments chain, so attributes contain attributes — UA:engineer → UA:staff, OA:research-docs → OA:company-files — building the two hierarchies (a user side and an object side) that give the graph its shape. An association is the grant that bridges the two sides: UA:engineer ⇒ {read, write} ⇒ OA:research-docs means “anyone contained in engineer may read and write anything contained in research-docs.” A prohibition is the explicit exception: UA:engineer ⊘ {delete} OA:company-files withholds delete regardless of any association that might otherwise grant it. That is the entire grammar — containers, grants, and denials over containers — and remarkably, it is enough to express the models of the previous five articles.


NGAC policy graph Everything in NGAC is a node in one directed graph. Assignment edges build attribute chains from users and objects up to a shared policy class. An association edge grants an operation set from a user attribute to an object attribute. A prohibition edge blocks an operation set the same way. Access is a reachable privilege path minus any prohibitions. access = a privilege path through the graph, minus prohibitions edge types assignment association prohibition Sara (user) Engineer (user attribute) Staff (user attribute) roadmap.md (object) Research Docs (object attribute) Company Files (object attribute) RBAC policy (policy class) assignment association: {read, write} prohibition: ✕ {delete}
An NGAC policy graph. Users and objects are assigned up into attribute containers; an association between a user attribute and an object attribute grants a set of operations; a prohibition subtracts one. A decision is a search for a privilege path from user to object — Sara reaches roadmap.md through Engineer ⇒ Research Docs — that no prohibition cuts.

How a decision is computed

Given the graph, deciding a request ⟨user, operation, object⟩ — “may Sara read roadmap.md?” — is a well-defined search, and its determinism is a big part of NGAC’s appeal. Informally, the engine does three things. First, it computes the attribute containers the user reaches by following assignment edges up from the user: Sara → engineer → staff. Second, it computes the attribute containers the object reaches: roadmap → research-docs → company-files. Third, it looks for an association whose source is one of the user’s containers, whose target is one of the object’s containers, and whose operation set includes the requested operation — here engineer ⇒ {read, write} ⇒ research-docs matches. If such a privilege path exists and no prohibition removes the operation along the way, the request is permitted; otherwise it is denied.


flowchart LR
  accTitle: How NGAC derives an access decision from the policy graph
  accDescr: The decision procedure begins with a request naming a user, an operation, and an object. The first step follows assignment edges upward from the user to collect all user attributes that contain the user, such as engineer and staff. The second step follows assignment edges upward from the object to collect all object attributes that contain the object, such as research docs and company files. The third step searches for an association whose source is one of the collected user attributes and whose target is one of the collected object attributes and whose operation set includes the requested operation — for example engineer to research-docs. If no such association exists, the result is deny. If one exists, a fourth step checks whether any prohibition removes the requested operation for this user over this object. If a prohibition applies, the result is deny; otherwise the result is permit.
  R["Request: user sara, op read, object roadmap"] --> UA["Collect user attributes above sara:<br/>engineer, staff"]
  R --> OA["Collect object attributes above roadmap:<br/>research-docs, company-files"]
  UA --> A{"Association linking a user attr to an object attr<br/>that includes read?<br/>e.g. engineer to research-docs"}
  OA --> A
  A -->|no| D1["DENY — no privilege path"]
  A -->|yes| P{"Any prohibition removes read here?"}
  P -->|yes| D2["DENY — prohibition wins"]
  P -->|no| PERMIT["PERMIT — privilege path survives"]
Deriving an NGAC access decision. The engine collects the user attributes reachable from the requesting user and the object attributes reachable from the target object, seeks an association linking the two sides that includes the requested operation, and finally checks that no prohibition removes it. A surviving privilege path is a permit; a missing path or an applicable prohibition is a deny.

Two properties of this procedure are worth dwelling on because they are NGAC’s headline advantages. First, it is deterministic and bounded: there is no rule-ordering ambiguity and no combining-algorithm subtlety to reason about — the answer is a function of the graph, and its cost scales with the graph’s size, not with an ever-growing pile of independently written rules. Second, and more distinctively, the same graph answers review queries as naturally as it answers access queries. “What can Sara access?” is: collect her user attributes, follow every association out of them, and enumerate the object attributes (and their contents) she reaches. “Who can delete this record?” is the mirror image. These per-user and per-object “review” questions — the ones auditors and access-recertification programs live on, and the ones RBAC and especially ABAC answer only with expensive enumeration — are native traversals in NGAC, because access is structural rather than computed by opaque rules.


Why one graph can be several policies: policy classes

A subtle but powerful feature is the policy class (PC). The same graph can contain multiple policies simultaneously, each rooted in its own policy class, and an element can be assigned upward into several of them. The rule that ties them together is strict: a request is granted only if it is granted under every policy class that governs the object. This is how NGAC expresses coexisting, independently authored policies — an RBAC-style policy and a data-classification policy and a project-confidentiality policy can all live in one graph, and access requires satisfying all of them at once, exactly like the intersection of concerns you meet in real governance.


This matters because real organizations never have just one policy. Legal wants classification rules; a business unit wants role rules; a project wants need-to-know rules — and access should require passing all three. In most models you would hand-code that intersection; in NGAC it is intrinsic, because each concern is a policy class and the decision procedure already requires all governing classes to grant. The conceptual schema above hints at this with a single “RBAC policy” class, but imagine a second “Classification” class over the same objects, and you have the multi-policy composition that NGAC handles as a first-class structural fact rather than as glue code.



Modeling the earlier models, concretely

The subsumption claim is easy to assert and worth making tangible, because seeing how NGAC becomes each earlier model is what turns “one framework for all of them” from a slogan into an intuition. Take RBAC first. A role is just a user attribute that groups users, and a permission is just an association from that attribute to an object attribute. Model UA:manager ⇒ {approve} ⇒ OA:expenses and you have exactly the role-grants-permission structure of the RBAC article; assign UA:senior-manager → UA:manager and you have role hierarchy as attribute containment; the constrained-RBAC separation-of-duty rule becomes a prohibition. RBAC, in NGAC’s terms, is the special case where the user attributes are named after jobs and access flows only through associations.


Now ABAC. Where RBAC used a handful of role-shaped attributes, ABAC uses many descriptive ones — department, clearance, region, project — and NGAC represents each as its own user or object attribute container, with associations bridging the ones that should grant access. “Engineers in the research project may read research documents” is an association from the intersection of UA:engineer and UA:research-project to OA:research-docs. The attribute-driven decisions of the ABAC article become associations over attribute containers, and the environmental conditions ABAC loved — time, risk — attach as constraints, the same seam we saw ReBAC hit. ReBAC, finally, is approached by using assignments to model the containment and ownership relationships between resources: a document assigned into a folder’s object attribute inherits the folder’s associations, which is exactly the folder-tree inheritance ReBAC expressed with tuple-to-userset. Three models, one graph, three configurations — that is the payoff of NGAC’s abstraction, and working an example through each is the fastest way to feel why the framework is called general.


Obligations: policy that rewrites itself

One element we have not yet used sets NGAC apart from most models: the obligation. An obligation is an event-response rule — “when this event occurs, automatically perform these administrative operations on the graph.” Because administrative actions in NGAC (creating assignments, associations, prohibitions) are themselves operations expressible in the model, an obligation can change the policy in reaction to events. “When a user opens a case, grant them access to that case’s records; when they close it, revoke it” becomes a pair of obligations that add and remove assignments automatically, with no out-of-band workflow. This makes NGAC capable of expressing dynamic, history-dependent policies — separation of duty that reacts to what a user has already done, break-glass grants that auto-expire, workflow-scoped access — inside the model rather than in surrounding code. It is the same instinct as PBAC’s obligations, generalized into “the policy can administer itself.”


NGAC versus XACML: two roads to fine-grained authorization

NGAC is best understood alongside XACML, the other major standard aimed at fine-grained, attribute-aware authorization (and the subject of the next module). They pursue the same goal by opposite means, and the contrast is illuminating:


DimensionXACMLNGAC
Policy formRules in a language (target/condition/effect)A directed graph of relations
EvaluationMatch request against rules, combine resultsTraverse the graph for a privilege path
Combining logicExplicit combining algorithms resolve conflictsDeterministic; prohibitions override grants
Review queriesExpensive — must evaluate against many subjectsNative graph traversals (“what can X access?”)
Multiple policiesPolicy sets with combining algorithmsPolicy classes; access needs all of them
Maturity / toolingOlder, broader historical adoptionNewer, thinner tooling, growing

The essence is that XACML computes decisions from rules while NGAC reads them from structure. XACML’s rule-and-combining-algorithm approach is enormously flexible but can become hard to reason about — with many policies and combining algorithms, “what does this actually decide, and why?” gets genuinely difficult, and answering “what can this user reach?” means evaluating the whole ruleset against them. NGAC’s graph makes evaluation deterministic and review queries cheap, at the cost of a newer ecosystem and the discipline of thinking in a graph. Neither is simply better; they are different shapes of the same ambition, and knowing both is how you evaluate any fine-grained authorization system you meet.


NGAC in practice: the reference implementation and beyond

Because NGAC is a standard rather than a product, using it means adopting an implementation of the model, and the same functional architecture recurs across all of them — the very architecture the next module formalizes. There is a Policy Decision Point that answers requests by traversing the graph, a Policy Enforcement Point in each application that asks and enforces, a Policy Administration Point where the graph is authored, and — unique to NGAC’s obligations — an Event Processing Point that watches for events and fires the administrative operations obligations describe. NIST publishes an open reference implementation of the Policy Machine so the model can be studied and exercised directly, and a small number of commercial platforms (attribute-based authorization vendors among them) build on or align with the standard. The ecosystem is unmistakably younger and narrower than the one around OPA/Rego or Zanzibar-style engines, which is the honest counterweight to NGAC’s conceptual elegance.


It helps to picture where NGAC realistically fits today. It is most compelling in environments that already think in attributes and need provable, reviewable access — government, defense, healthcare, and large regulated enterprises, the same settings where MAC and formal models historically found their home. In those places the ability to answer “exactly who can reach this record, and under which policies?” by reading a graph is worth real investment, and the determinism reassures auditors in a way a pile of combinable rules does not. For a typical web application reaching for authorization today, a Zanzibar-style engine or an OPA policy will usually have more community, more examples, and a gentler on-ramp. NGAC is the model to understand universally and to deploy selectively — which is precisely how a unifying framework tends to enter the world, ideas first and infrastructure after.


Strengths and honest limitations

NGAC’s strengths follow directly from its design. It offers genuine generality — one framework for role-, attribute-, and relationship-style policy, which means you can mix them without switching engines. Its evaluation is deterministic and analyzable, avoiding the combining-algorithm ambiguity that makes large rule sets hard to trust. Its review queries are efficient, which is a real operational gift: access recertification, “who can touch this?”, and “what can they reach?” are the questions governance actually asks, and NGAC answers them by construction. And prohibitions and obligations let it express denials and dynamic, self-modifying policy that many models cannot state at all.


The limitations are equally real and worth stating plainly. Adoption and tooling are still early — compared with the rich ecosystem around RBAC, OPA/Rego, or Zanzibar-style engines, NGAC has fewer production implementations, fewer libraries, and a smaller community, so choosing it means building more yourself. There is a conceptual learning curve: thinking in assignments, associations, and prohibitions over attribute containers is unfamiliar, and a mis-modeled graph is as capable of a security bug as any other mechanism. And operating the graph at scale — keeping it correct as attributes and assignments churn, and evaluating it with low latency — is its own engineering problem, the same freshness-and-performance tension the whole module keeps circling. NGAC is, today, more influential as a way of thinking than as a default deployment choice — but the way of thinking is the part worth internalizing.



A worked example: Sara’s roadmap, one last time

The graph in the figure is the worked example, so trace the decision end to end. Sara is assigned to UA:engineer, which is assigned to UA:staff; roadmap.md is assigned to OA:research-docs, which is assigned to OA:company-files. An association engineer ⇒ {read, write} ⇒ research-docs grants read and write across those containers. When Sara requests read on roadmap.md, the engine collects her attributes (engineer, staff), collects the object’s attributes (research-docs, company-files), finds the association linking engineer to research-docs with read in its set, checks that no prohibition removes it — and permits. When she requests delete on the same object, no association grants delete, and even the broader company-files container carries a prohibition engineer ⊘ {delete} — so the request is denied twice over. Every earlier model reached the same verdict; NGAC reaches it by reading the graph’s structure.


Now see the unification concretely. Add a second policy class — a classification policy — over the same objects, with its own association granting read on research-docs only to UA:cleared. Access to roadmap.md now requires satisfying both policy classes: Sara must be an engineer (the role policy) and be cleared (the classification policy). That is RBAC and a classification model composing in one graph, with no glue code — the exact scenario that, in the earlier articles, forced a hybrid stitched together by hand. And because obligations can add assignments on events, you could make “cleared” itself grant automatically when Sara completes a training event, letting the policy evolve without an administrator. This is what “one model to express them all” buys: not less thought, but one place for all of it.


Recap

Next-Generation Access Control unifies the earlier models in a single graph:


  1. One directed graph for everything. Users, user attributes, objects, object attributes, and policies are nodes; assignments (containment), associations (grants), and prohibitions (denials) are edges. A decision is a search for a privilege path from user to object.
  2. A small, expressive grammar. Assignments build user- and object-attribute hierarchies; an association grants operations from a user attribute to an object attribute; a prohibition subtracts them and overrides grants.
  3. It subsumes RBAC, ABAC, and ReBAC as configurations of one framework — the standardized form of NIST’s Policy Machine (INCITS 565), from the same lineage as RBAC.
  4. Deterministic evaluation and native review queries are its standout advantages: “what can this user access?” and “who can access this object?” are graph traversals, and policy classes let multiple policies coexist with access requiring all of them; obligations let the policy modify itself on events.
  5. Adoption and tooling are still early, and generality costs abstraction — so NGAC is, for now, most valuable as a unifying way to think about authorization, even where it is not the deployed engine.


Three questions to test yourself

  1. Define assignment, association, and prohibition in NGAC, and use all three to write the graph edges that would let engineers read and write research documents but never delete company files. Which edge type carries the operation set, and which one overrides the others?
  2. Explain how NGAC answers “what can this user access?” as a graph traversal, and why the same question is expensive in ABAC. Why does this make NGAC attractive for access recertification and audit?
  3. NGAC claims to subsume RBAC, ABAC, and ReBAC. Pick two of those models and describe, concretely, what you would configure in an NGAC graph to make it behave like each — and explain what NGAC’s generality costs you in exchange.

Hands-on exercises

  1. Model a two-policy graph on paper. Draw an NGAC graph with one RBAC-style policy class (an engineer user attribute granted read/write on a research-docs object attribute) and one classification policy class (a cleared user attribute granted read on the same objects). Place a user in both, and trace why a request is permitted only when both policy classes grant it.
  2. Add a prohibition and an obligation. Extend your graph with a prohibition that denies delete on a company-files container, and describe an obligation of the form “when a user is assigned to engineer, automatically assign them to staff.” Explain how each changes the decisions the graph produces.
  3. Compare a decision with XACML. Take one access rule and express it twice — once as an NGAC association (plus any prohibition) and once as an XACML-style rule with a target, condition, and effect. List what becomes easy in each representation, focusing on how you would answer “who can do this?” in both.

Frequently asked questions

What is Next-Generation Access Control (NGAC)?

Next-Generation Access Control is a standardized access-control framework (ANSI/INCITS 565, developed from NIST's Policy Machine) that represents users, user attributes, objects, object attributes, and policies as elements of a single directed graph, and computes an access decision by finding a privilege path from the requesting user to the target object through that graph. Assignment edges place elements into attribute containers, association edges grant operations between attribute sets, and prohibitions subtract access. Because roles, attributes, and relationships can all be expressed as the same graph structure, NGAC is designed as a general framework that subsumes RBAC, ABAC, and ReBAC rather than competing with them.

How does NGAC differ from XACML?

Both are standards for fine-grained, attribute-aware authorization, but they take different shapes. XACML expresses policy as a set of rules written in a language and evaluated by matching a request against them; NGAC expresses policy as a directed graph of relations and evaluates by traversing it. The practical consequences are that NGAC evaluation is deterministic and its complexity is bounded by the graph rather than by rule-combining logic, that NGAC can answer 'review' questions efficiently — what can this user access, and who can access this object — by walking the graph, and that a single NGAC graph can hold multiple coexisting policies as separate policy classes. XACML has broader historical tooling; NGAC offers a more analyzable, unified data model.

What are assignments, associations, and prohibitions in NGAC?

They are the three core edge types of the NGAC graph. An assignment places one element inside another — a user into a user attribute, an object into an object attribute — forming containment hierarchies, and assignments are what give NGAC its structure. An association is the grant: it connects a user attribute to an object attribute with a set of operations, meaning 'members of this user attribute may perform these operations on members of this object attribute.' A prohibition (or deny) explicitly withholds operations from a user or attribute over some object set, and prohibitions override grants, letting NGAC express exceptions that pure grant-based models cannot.

Does NGAC replace RBAC and ABAC?

Not by competing on the same axis — NGAC is better understood as a general framework in which RBAC and ABAC are special cases. Model user attributes as roles and you have RBAC inside NGAC; model them as arbitrary attributes with associations conditioned on attribute containers and you have ABAC inside NGAC; model containment and relationships as assignments and you approach ReBAC. NGAC's ambition is to be the single formal structure that can express all of these at once, so an organization can mix role-, attribute-, and relationship-style rules in one policy without switching engines. Whether it replaces the others in practice depends on tooling and adoption, which are still maturing.

What is the Policy Machine?

The Policy Machine is the NIST research model, led by David Ferraiolo and colleagues, that NGAC standardizes. It defined the idea of a general-purpose access-control mechanism whose behavior is entirely determined by a configurable graph of users, attributes, objects, operations, associations, prohibitions, and obligations — so that different access-control policies (RBAC, ABAC, multi-level, and combinations) are just different configurations of the same machine rather than different mechanisms. NGAC (INCITS 499 and later INCITS 565) is the standardized expression of the Policy Machine's model, and NIST provides a reference implementation.