Externalised authorisation only pays off if applications can ask a policy engine for a decision without being rewritten for each engine's proprietary API. Until recently every policy decision point (PDP) had its own request format, so changing engines meant touching every policy enforcement point (PEP) in every application, gateway and agent tool. The OpenID Foundation's AuthZEN working group published Authorization API 1.0 as a Final Specification on 11 January 2026, giving PEPs and PDPs a common JSON-over-HTTPS contract for single decisions, batches and "what can this user access" searches. This guide explains the information model, each endpoint, discovery, the security requirements, how to adopt it and how to measure it. It is for application architects, API platform teams and IAM engineers building or buying fine-grained authorisation; for choosing a product, see the Externalised Authorisation Buyer's Guide.
Key takeaways
- It standardises the question, not the policy. AuthZEN defines how a PEP asks and how a PDP answers; policy languages and engines (Rego, Cedar, XACML-style, relationship graphs) stay behind the API.
- It is a Final Specification. Authorization API 1.0 reached Final status in January 2026 after an Implementer's Draft in November 2024, so the core endpoints are stable to build on.
- Four nouns carry every request. Subject, resource, action and context, each with a type and identifier plus optional properties, map cleanly onto RBAC, ABAC and ReBAC models.
- A denial is not an error. A denied request returns HTTP 200 with
"decision": false; HTTP errors mean the call itself failed, and the PEP must fail closed. - Search changes user interfaces and queries. The subject, resource and action search endpoints answer "what may this user see" without the application reimplementing policy.
Where AuthZEN sits in an authorisation architecture
The PEP is the code that enforces a decision: middleware in an application, a filter in an API gateway, a sidecar, or the tool layer of an MCP server. The PDP evaluates policy and returns a decision. AuthZEN defines the interface between them. In the specification's words the API lets the two exchange requests and decisions without knowing each other's internals, with a normative HTTPS JSON binding and a transport-agnostic design. The working group's charter is explicit that it builds on existing architectures rather than defining a new policy language.
| Component | Role | What AuthZEN changes |
|---|---|---|
| Application or gateway (PEP) | Builds the request, enforces the decision | One client library and request shape for any conformant PDP |
| Policy engine (PDP) | Evaluates policy against inputs | Exposes standard endpoints alongside any native API |
| Policy information sources | Supply attributes and relationships | Unchanged; the PDP fetches them or the PEP sends them as properties |
| Policy administration | Authoring, testing, versioning | Unchanged and engine-specific. See the Policy-as-Code for Authorisation Guide |
The information model
- Subject:
type(required),id(required, unique within the type) and optionalproperties. A user, a service, a workload or an AI agent; for example typeuser, id an email or stable identifier. - Resource:
type,idand optionalproperties, for example typedocument, iddoc-123, with an owner or classification property. - Action:
name(required) and optionalproperties, for examplecan_readorapprove. - Context: optional environmental data such as time, device posture, IP address or authentication strength.
- Decision: a required boolean
decisionand an optionalcontextobject for reasons, obligations or step-up hints.
The model fits all the common authorisation styles: roles as subject properties for RBAC, attributes across all four objects for ABAC, and type plus id pairs that match relationship tuples for ReBAC. See the Authorisation Models Guide and the Fine-Grained Authorisation Guide.
Decision context matters: the specification lets a PEP reject a true decision if it does not understand required content in the response context. Treat unknown obligations as a deny, not as an approval with a warning.
The endpoints
| API | Default path | Asks | Returns |
|---|---|---|---|
| Access Evaluation | POST /access/v1/evaluation | May this subject perform this action on this resource? | One decision |
| Access Evaluations (batch) | POST /access/v1/evaluations | Many checks in one call, with shared defaults | Decisions in request order |
| Subject Search | POST /access/v1/search/subject | Which subjects of a type may do this action on this resource? | results array, paged |
| Resource Search | POST /access/v1/search/resource | Which resources of a type may this subject act on? | results array, paged |
| Action Search | POST /access/v1/search/action | Which actions may this subject perform on this resource? | results array, paged |
A single evaluation in practice
An expense application needs to know whether Alice may approve report 42. Its PEP has already validated Alice's access token. It posts to the evaluation endpoint a subject of type user with Alice's stable identifier and a department property, an action named approve, a resource of type expense_report with id 42 and properties for amount and submitter, and a context carrying the authentication method from the token. The PDP's policy might say managers may approve reports from their own department below a threshold, never their own. The response is {"decision": true} or {"decision": false}, optionally with a context explaining a denial or demanding step-up. The application never sees the policy, and the same request shape works whichever engine sits behind the endpoint.
Decide early which side supplies attributes. Sending properties from the PEP is fast but trusts the application's data; letting the PDP look them up from authoritative sources is slower but harder to manipulate. A mixed model, with identity attributes from the token and resource attributes looked up by the PDP, is common.
Batch evaluations
The batch request carries an evaluations array. Top-level subject, action, resource and context act as defaults that individual items override, which keeps payloads small when one user is checked against many resources. The optional options.evaluations_semantic takes one of three values:
- execute_all (default): evaluate everything and return every result, useful for rendering a page of buttons.
- deny_on_first_deny: stop at the first denial or failure, a logical AND, useful when an operation needs several permissions.
- permit_on_first_permit: stop at the first permit, a logical OR, useful when any one of several routes grants access.
Per-item failures appear in that item's context, for example as an error with a status and message, and decisions default to closed.
Search and paging
Search requests omit the id of the entity being searched for. Paging uses a request page object with token and limit, and a response page with next_token (an empty string signals the end) and optional count and total. All parameters except the token must stay identical across pages, and pages are not an atomic snapshot, so results can repeat or be missed if data changes. The specification says search results should evaluate to true in an access evaluation but does not guarantee it: for sensitive actions, re-check with the evaluation endpoint before acting.
Discovery, transport and errors
- Metadata: a PDP publishes JSON at
/.well-known/authzen-configuration(inserted between host and path, per RFC 8615) withpolicy_decision_pointandaccess_evaluation_endpointrequired, and optionalaccess_evaluations_endpoint, the three search endpoints,capabilitiesandsigned_metadata. Thepolicy_decision_pointvalue must match the identifier used to fetch it, or the metadata must not be used. An absent endpoint means the PDP does not support that API. - Transport: HTTPS
POSTwithContent-Type: application/json; success is 200; 400 for a malformed request, 401 when the PEP failed authentication (withWWW-Authenticate), 403 and 500 as usual. - Correlation: an optional
X-Request-IDheader that the PDP must echo, which ties PEP and PDP logs together. - Extensibility: receivers ignore unknown fields, and paths should carry
v1so later versions can coexist. - Registries: the specification sets up IANA registries for PDP metadata and for capability URNs, so vendor extensions can be advertised interoperably.
Security requirements and hardening
| Area | Specification position | Hardening choice |
|---|---|---|
| Transport | PEP to PDP connection MUST be secured, for example with TLS | TLS everywhere, including sidecar and localhost PDPs on shared hosts |
| PEP authentication | PDP SHOULD authenticate the PEP (mutual TLS, OAuth or API keys) | Prefer mTLS or OAuth client credentials over static API keys; keys are NHIs that leak. See the mTLS Guide |
| Input trust | PDP assumes the PEP sends accurate values | Derive subject from a validated token at the PEP, never from a client-supplied field |
| Response integrity | PDP MAY sign responses | Sign where decisions pass through intermediaries or must be non-repudiable |
| JSON handling | SHOULD follow I-JSON (RFC 7493); omit nulls | Strict parsing; reject duplicate keys |
| Denial of service | PDP SHOULD limit payload size, rate, nesting and memory | Cap batch size and search page limit; rate-limit per PEP identity |
| Metadata trust | Unsigned metadata relies on TLS; signed metadata must be validated | Pin PDP identifiers in configuration; validate signed_metadata if used |
The PEP is where most AuthZEN deployments go wrong. The PDP decides on what it is told: if the gateway passes a user ID taken from a request parameter rather than from a verified token, the policy engine will faithfully authorise the attacker. Pair AuthZEN with token validation at the edge and, inside a service estate, with signed context such as Transaction Tokens. See the OAuth Transaction Tokens Guide.
Where identity fits
Every AuthZEN subject is an identity, and many are non-human. Model service accounts, workloads and AI agents as their own subject types rather than borrowing the user type, so policy can treat an agent acting for a user differently from the user. For agent tool calls, a PEP in the MCP server or gateway can send the user as subject, the agent client as a subject property or context value, and the tool invocation as the action. See the AI Agent Authorisation Guide. The credential the PEP itself uses to call the PDP is also an NHI: give each PEP its own identity so the PDP can rate-limit, audit and revoke it individually.
Choosing how to adopt
| Situation | Approach |
|---|---|
| New application or API platform | Build PEPs against AuthZEN from the start; require it in PDP selection |
| Existing PDP with a native API | Check whether the vendor or project exposes AuthZEN endpoints; migrate PEPs gradually, gateway first |
| Many languages and teams | One shared PEP library or gateway filter speaking AuthZEN, so policy changes never need app releases |
| List filtering in user interfaces | Resource search for moderate result sets; for very large datasets, engine-specific query filtering may still be needed |
| Latency-critical paths | Co-located PDP (sidecar or library) behind the same API, with batch calls to cut round trips |
Small organisations gain most from AuthZEN as a hedge: build the PEP once against the standard and keep the freedom to change engines. Large organisations can use it to standardise dozens of bespoke permission checks across business units on one contract, and to run more than one PDP behind a common interface. The working group states it is developing a conformance certification programme for PDPs; until it exists, test claims of support yourself.
How to implement
- Inventory authorisation checks in one application or gateway: where decisions are made in code today and what inputs they use.
- Define subject, resource and action types and naming conventions organisation-wide, including non-human subject types.
- Stand up a PDP that exposes AuthZEN endpoints, fetch its
/.well-known/authzen-configuration, and confirm the endpoints it advertises. - Build or adopt a PEP library that derives the subject from verified tokens, sends
X-Request-ID, enforces timeouts and fails closed on any non-200 response or unknown obligation. - Shadow mode: call the PDP alongside existing in-code checks and log disagreements for two to four weeks without enforcing.
- Enforce route by route, starting with read actions, then writes and administration.
- Add batch and search where pages render many permission-dependent elements or lists.
- Rollback: keep the legacy check behind a feature flag per route until the PDP path has run clean through a full release cycle.
Detection and measurement
- Decision logs: request ID, PEP identity, subject type and id, action, resource type and id, decision, policy version and latency, with sensitive properties masked.
- Alerts: spikes in 401 responses (a PEP credential problem or probing), deny-rate jumps after a policy release, unknown PEP identities, and oversized batch or search requests.
Metrics: share of authorisation checks served through AuthZEN rather than in-code logic; shadow-mode disagreement rate before enforcement; p99 decision latency per endpoint; PDP availability; percentage of PEPs authenticating with mTLS or OAuth rather than API keys.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev 5 | AC-3 Access Enforcement; AC-24 Access Control Decisions; AC-6 Least Privilege; AC-16 Security and Privacy Attributes; AU-2 Event Logging | Separated decision and enforcement, attribute-based decisions, decision logs |
| NIST CSF 2.0 | PR.AA-05 | Access permissions defined in policy, enforced and reviewed |
| ISO/IEC 27001:2022 Annex A | 5.15 Access control; 8.3 Information access restriction; 8.15 Logging | Central policy with per-request restriction and evidence |
| CIS Controls v8.1 | Control 6 Access Control Management; Control 16 Application Software Security | Consistent access control in applications |
| OWASP API Security Top 10 2023 | API1 Broken Object Level Authorization; API5 Broken Function Level Authorization | Object and function checks moved to a consistent PDP call. See the OWASP API Top 10 API1 Broken Object Level Authorization Guide |
Common failure patterns
- Trusting client-supplied subjects. The PDP assumes PEP inputs are accurate; a PEP that copies the user ID from the request body hands authorisation to the caller.
- Failing open on PDP errors or timeouts to protect availability, which converts every outage into an authorisation bypass.
- Treating search results as decisions for sensitive actions, despite the specification saying they are not guaranteed to match an evaluation.
- Ignoring decision context. Accepting a
truedecision while discarding a required obligation, such as step-up or redaction. - Shared static API keys for every PEP, so one leaked key gives policy-probing access and individual PEPs cannot be revoked.
- Logging full properties containing personal or sensitive data in decision logs without masking.
Practitioner checklist
- Agree organisation-wide subject, resource and action type names, including non-human subjects.
- Require AuthZEN Authorization API 1.0 support when selecting a PDP.
- Derive subjects only from verified tokens at the PEP.
- Fail closed on non-200 responses, timeouts and unknown obligations.
- Authenticate each PEP to the PDP with its own credential, preferably mTLS or OAuth.
- Use batch evaluations with an explicit
evaluations_semantic. - Re-check sensitive actions with the evaluation endpoint after a search.
- Send and log
X-Request-IDwith policy version and decision. - Cap batch size, page limit and request rate per PEP.
- Run shadow mode before enforcing on each route.
Standards and references
- OpenID Foundation: Authorization API 1.0
- OpenID Foundation: AuthZEN Working Group
- IETF: Transaction Tokens (draft-ietf-oauth-transaction-tokens)
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- OWASP: API1:2023 Broken Object Level Authorization
Related NHI Mgmt Group resources: Externalised Authorisation Buyer's Guide · Policy-as-Code for Authorisation Guide · Authorisation Models Guide · Fine-Grained Authorisation Guide