Policy model
PolicyArc decides each token request with Open Policy Agent (OPA). OPA runs beside the authorization server and evaluates two things the server sends it, Rego rules and data rows. You change a decision by writing a data row or by deploying a rule. You do not change or restart the server.
Rules and data
Rules are Rego files. The product ships the protocol policies, such as oauth/token.rego, and the shipped controls. You add your own controls as files of your own.
Data rows are JSON. Most shipped controls read their settings from a row named pbac.operator.controls.<control>, such as the denylist row. Controls and segments explains how a control and its row fit together.
The server stores both in its database. It packs them into one bundle, a gzipped tar file of .rego files and a data.json, and serves it at GET /bundles/pbac/bundle.tar.gz. OPA long-polls that endpoint, and the server wakes the poll when a rule or row changes. A change reaches decisions a few seconds after you save it. We saw a data write take effect within about three seconds.
How a token request is decided
The token policy, oauth.token, works through the request in this order.
- It refuses the request outright on a protocol check. These include a client or subject on the denylist, a grant the client is not entitled to, and a public client asking for client credentials.
- It resolves what the client is entitled to. A
client_identry in the client entitlements row comes first, then asoftware_identry keyed by the software statement'ssubclaim, then the client's software statement. - It keeps the requested resources the client is entitled to.
- It evaluates each kept resource, once for each requested action. An action is refused when a subject restriction or the resource's own scope list rules it out, or when any control adds a reason to
deny. - It grants the actions that survived. The request fails when no resource the client named has a surviving action.
Every reason a control added goes into the decision as deny_reasons, whether the request was refused or narrowed. A refused request also gets one reason, such as client_denied or all_resources_denied. The audit log keeps both.
Where your own controls run
The aggregator package oauth.evaluations_ext collects deny, obligations and token lifetimes from every package under pbac.controls and every connector package under pbac.connectors. You add a control by deploying a file in its own package. Nothing else is edited.
Contributions combine without priority. Denial reasons and obligations are unions, the shortest token lifetime wins, and single use wins when any control asks for it. A control you add cannot remove another control's denial.
The token, introspect and authorize policies run your controls. Registration and the AuthZEN evaluation endpoint use other policies and do not. Rego input and output lists the entry points.
Next steps
Send feedback about this page