Clients and access
A client is anything that asks the authorization server for a token, such as a web app, a backend service or an AI agent. Policy decides what each client gets from three things. It looks at how the client registered, what the client is entitled to, and which resource types it asks for.
What policy sees of a client
Every decision carries the client under input.context.client. These fields come from a real token request.
| Field | Meaning |
|---|---|
client_id | The client's id |
client_type | confidential when the client holds a secret, public when it cannot |
registration_type | How the client registered. See the next table. |
software_statement | Every claim of the client's software statement, or {} when it has none |
is_resource_server | Whether the client is a resource server that calls introspection |
dpop_bound_access_tokens | Whether the client's tokens are bound to a DPoP key |
redirect_uri | The redirect URI of this request, when it has one |
How a client registers
registration_type takes one of five values.
| Value | How the client got here |
|---|---|
PRE_REGISTERED | The default, for a client that did not come through /register, such as one an operator created |
SOFTWARE_STATEMENT | It registered at /register with a signed software statement from a trusted issuer |
DCR_PLAIN | It registered at /register with no statement |
CIMD | It presented a client metadata document by URL |
SPIFFE_SVID | It is a workload that authenticates with a SPIFFE ID |
A software statement is a signed JWT that says what the client is and what it may request. The server accepts one only from an issuer in the trusted issuers row, pbac.operator.controls.trust. Every claim in it reaches policy, including claims you add yourself. Attribute-based access uses a department claim this way.
Resource types and scopes
Policy grants access to resource types, and each type has a list of scopes. The types live in the resource registry row, pbac.operator.controls.resource_registry. A new instance ships four of them, for user info, introspection, AuthZEN and MCP servers.
A client names what it wants in the token request. It can send a resource indicator in resource, which must resolve to a known type, or name the type in resource_types. When we sent a resource the server could not resolve, it answered invalid_target with Resource could not be resolved to a known type.
Entitlements
An entitlement says which grant types a client may use and which scopes of which types it may receive. The token policy takes the first of these that exists.
- An entry for the
client_idin the client entitlements row,pbac.operator.controls.client_entitlements - An entry under
software_idin the same row, keyed by thesubclaim of the client's software statement - The
grant_typesandgranted_resourcesclaims of the client's software statement
A SPIFFE client has no software statement. Its entitlement comes from path_grants in the SPIFFE row, pbac.operator.controls.spiffe_policy, keyed by its SPIFFE ID path.
A new instance also ships bindings that entitle every DCR_PLAIN and CIMD client to the authorization_code and refresh_token grants, to openid, profile and email on urn:as:userinfo, and to mcp:tools and mcp:resources on urn:mcp:server over the MCP interface only. A managed resource that is exposed over MCP adds one entry for its own type when you register it. There is no read scope and no entry for every type, so these clients get nothing on a REST-only resource without an entitlement of their own. A binding adds to what the entries above resolved. Control data shows how to write an entitlement.
The granted scopes are what the client asked for, cut down to its entitlement, and then cut down again by any control that denies an action. Policy model walks through that order.
Next steps
Send feedback about this page