| Internet-Draft | Rego Policy in OAuth | March 2026 |
| Liu, et al. | Expires 18 September 2026 | [Page] |
This specification defines how to use the Rego policy language in OAuth 2.0 authorization flows using Rich Authorization Requests (RAR). It defines the rego_policy authorization data type for carrying policy proposals in authorization_details, enabling fine-grained, dynamic authorization decisions that go beyond traditional scope-based access control.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 18 September 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Traditional OAuth 2.0 authorization relies on static scopes to define access permissions. While scopes work well for coarse-grained access control, they are insufficient for scenarios requiring dynamic, context-aware authorization decisions—particularly in AI agent systems where the permitted operations may depend on runtime conditions such as transaction amounts, time windows, or resource attributes.¶
This specification extends OAuth 2.0 [RFC6749] to support the Rego policy language, as used by Open Policy Agent (OPA) [OPA]. Rego [Rego] enables expressive, declarative policies that can encode complex authorization rules. By integrating Rego into OAuth flows, this specification enables:¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals.¶
This specification defines the rego_policy
authorization data type for use with Rich Authorization Requests (RAR)
[RFC9396]. The policy proposal is carried within the
authorization_details parameter as the primary mechanism.¶
Key aspects of the RAR integration:¶
rego_policy type is defined for use with the
authorization_details parameter per RFC 9396.
It contains the policy content, entry point, and optional context.¶
authorization_details as the primary mechanism for
carrying policy information. The policy_ref claim
MAY be included as a lightweight alternative
(see Section 3.2).¶
Implementations SHOULD ensure consistency between
authorization_details requirements and Rego policy evaluations.
The Authorization Server MAY use RAR types to determine applicable
policy templates or validation rules.¶
authorization_details parameter.¶
authorization_details parameter.¶
policy_ref claim defined in this specification.¶
+--------+ +--------+ +--------+ +--------+
| Client | | AS | | RS | |Policy |
| | | | | | |Engine |
+--------+ +--------+ +--------+ +--------+
| | | |
| (1) AuthZ Req | | |
| with | | |
| authorization_ | | |
| details | | |
| (type=rego_ | | |
| policy) | | |
|--------------->| | |
| | | |
| | (2) Validate | |
| | policy syntax | |
| | | |
| | (3) Scope | |
| | check | |
| | | |
| (4) Enriched | | |
| Access Token| | |
| with authz_ | | |
| details | | |
|<---------------| | |
| | | |
| (5) API Request| | |
| with token | | |
|-------------------------------->| |
| | | |
| | | (6) Extract |
| | | policy from |
| | | authz_details |
| | | |
| | | (7) Evaluate |
| | | policy |
| | |--------------->|
| | | |
| | | (8) Result |
| | |<---------------|
| | | |
| | | (9) Enforce |
| | | decision |
| | | |
| (10) Response | | |
|<--------------------------------| |
authorization_details containing an object of type
rego_policy, with policy and optional
context fields. This leverages RAR (RFC 9396) for structured
authorization requests.¶
authorization_details array per RFC 9396
Section 7.1, containing the validated policy.¶
authorization_details in the
access token.¶
Traditional OAuth error responses indicate authorization failure without providing guidance on how to obtain valid authorization. In AI agent scenarios, where agents may need to autonomously navigate authorization requirements, resource servers can provide structured guidance that enables agents to construct appropriate authorization requests.¶
When an agent's request lacks sufficient authorization, the resource
server returns an HTTP 403 Forbidden response with a JSON body containing
a rego_profile object. This object provides machine-readable
guidance on the required authorization conditions.¶
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "insufficient_authorization",
"error_description": "Additional authorization required",
"rego_profile": {
"profile_uri": "https://resource.example/policies/purchase",
"required_scope": ["purchase.create"],
"required_claims": ["agent_id", "user_id"],
"constraints": {
"max_amount": {
"type": "number",
"description": "Maximum transaction amount in USD",
"required": true
},
"trigger_source": {
"type": "string",
"enum": ["user_initiated", "scheduled"],
"description": "Source of the operation trigger"
}
},
"confirmation_required": true,
"evidence_required": true,
"auth_server": "https://as.example.com"
}
}
The rego_profile object contains the following fields:¶
type (data type),
description (human-readable explanation),
enum (allowed values), and required
(boolean, whether the constraint must be provided).¶
interaction_required error code
and interaction flow.¶
Upon receiving a reverse-guided authorization response, the AI agent SHOULD:¶
rego_profile to understand authorization requirements.¶
auth_server is trusted before
proceeding.¶
confirmation_required is true, initiate user consent flow.¶
auth_server's metadata (RFC 8414) and
submit the authorization request.¶
This adaptive approach enables agents to "learn" authorization requirements dynamically, reducing the need for pre-programmed knowledge of each resource server's policies.¶
Implementations of reverse-guided authorization MUST consider the following security aspects:¶
auth_server specified in the rego_profile is trusted
before submitting authorization requests. Agents MUST
use only the token endpoint discovered from the
auth_server's Authorization Server Metadata
([RFC8414]). Blindly following
redirects could lead to credential theft.¶
Upon receiving an authorization_details request containing the
rego_policy type, the AS MUST perform the following
validation steps:¶
allow rule.¶
http.send, excessive resource consumption).¶
actions, locations)
for scope checking rather than analyzing the Rego policy
AST (see Section 3.1).¶
When the AS issues a policy_ref claim instead of
embedding the full policy in authorization_details,
the AS MUST register the policy:¶
When the AS embeds the validated policy directly in the
enriched authorization_details (the primary path),
explicit registration is not required — the policy travels
with the token.¶
If policy validation fails, the AS MUST return an error:¶
{
"error": "invalid_request",
"error_description": "Invalid Rego policy: syntax error at line 5"
}
The RS obtains the Rego policy from the access token. The
primary mechanism is to extract the policy from the enriched
authorization_details array included in the token
per RFC 9396 Section 7.1.¶
When the token uses the policy_ref claim instead
of inline policy content, the RS retrieves the policy using
one of the following methods:¶
After extracting the Rego policy from the token, the RS MUST load the policy into a Rego-compatible policy engine before querying it. Common loading mechanisms include:¶
PUT /v1/policies/{id} to register
the policy, then query the Data API;¶
Once loaded, the RS queries the policy engine with the request context as input:¶
POST /v1/data/agent/allow HTTP/1.1
Host: opa.example.com
Content-Type: application/json
{
"input": {
"user": {
"id": "user_12345",
"tier": "premium"
},
"action": "manage_portfolio",
"resource": {
"type": "portfolio",
"id": "portfolio_001"
}
}
}
{
"result": true
}
Based on the policy engine's response:¶
result is true: Allow the operation;¶
result is false: Deny with
403 Forbidden;¶
result is undefined (OPA returns an empty
object with no result field): Deny with
403 Forbidden. Note that policies following the
RECOMMENDED default allow = false pattern
(see Section 3.1.3) will always produce a defined
boolean result, so undefined only occurs when the
default declaration is omitted;¶
The rego_policy authorization data type defined in this
specification can be used with any OAuth 2.0 authorization flow
that supports Rich Authorization Requests (RAR)
[RFC9396]. This section illustrates usage with
flows that are particularly relevant to AI agent scenarios.¶
The JWT Authorization Grant Interaction Response
[I-D.parecki-oauth-jwt-grant-interaction-response]
is the RECOMMENDED flow for AI agent scenarios. In this flow,
an agent presents a JWT assertion to the token endpoint. If
user interaction (e.g., consent) is required before the token
can be issued, the AS returns an interaction_required
error with an interaction_uri where the user can
complete the interaction. The agent then polls for the token.¶
When combined with Rego Policy, the agent includes
authorization_details containing the
rego_policy type in the JWT grant request. The AS
validates the policy proposal, performs scope checks, and
determines whether user consent is needed before issuing
the token.¶
POST /token HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer &assertion=eyJhbGciOiJSUzI1NiJ9... &authorization_details=%5B%7B%22type%22%3A%22rego_policy%22%2C %22policy%22%3A%7B%22type%22%3A%22rego%22%2C %22content%22%3A%22package%20agent%5Cn... %22entry_point%22%3A%22allow%22%7D%2C %22actions%22%3A%5B%22manage_portfolio%22%2C%22view_reports%22%5D%7D%5D
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "interaction_required",
"interaction_uri": "https://as.example.com/interact/abc123",
"interval": 5,
"expires_in": 600
}
After the user completes the interaction, the agent retries
the same JWT grant request. The AS then issues the access
token with the enriched authorization_details
containing the validated Rego policy.¶
In machine-to-machine scenarios using client credentials, the policy proposal can be included in the token request:¶
POST /token HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded grant_type=client_credentials &client_id=spiffe%3A%2F%2Fagent.example%2Fagent &client_secret=... &authorization_details=%5B%7B%22type%22%3A%22rego_policy%22%2C %22policy%22%3A%7B%22type%22%3A%22rego%22%2C%22content%22%3A%22...%22%2C %22entry_point%22%3A%22allow%22%7D%7D%5D
When exchanging tokens [RFC8693], a new policy proposal can be provided to refine or restrict the authorized operations:¶
POST /token HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange &subject_token=eyJhbGciOiJSUzI1NiJ9... &subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token &authorization_details=%5B%7B%22type%22%3A%22rego_policy%22%2C %22policy%22%3A%7B%22type%22%3A%22rego%22%2C%22content%22%3A%22...%22%2C %22entry_point%22%3A%22allow%22%7D%7D%5D
The resulting access token will include the new, more restrictive policy constraints that MUST be a subset of the original token's permissions.¶
Rego policies submitted by clients are evaluable policy definitions. Although Rego is declarative and guarantees termination, the AS MUST:¶
Clients MUST NOT be able to propose policies that exceed their registered permissions. The AS SHOULD maintain policy templates or scope hierarchies to enforce this.¶
The policy_ref in access tokens MUST reference policies stored securely by the AS. Resource Servers MUST fetch policies only from trusted sources.¶
When the policy.uri field is present, the AS fetches
policy content from a client-provided URI. This introduces
Server-Side Request Forgery (SSRF) risks. The AS MUST:¶
Rego policies embedded inline within authorization_details can significantly increase token request and access token size. Implementations MUST enforce limits on:¶
For policies exceeding these limits, clients SHOULD use
pre-registered policies referenced via policy_ref
rather than inline policy content.¶
This specification defines the following authorization data type
for use with the authorization_details parameter
defined in RFC 9396:¶
This specification registers the following claims in the "JSON Web Token Claims" registry:¶
This specification registers the following error code in the "OAuth Extensions Error" registry established by RFC 6749:¶
rego_profile object in the response body to guide
the client toward obtaining sufficient authorization.¶
package agent
default allow = false
# Allow transactions up to $50
allow {
input.action == "purchase"
input.amount <= 50.0
}
# Allow cart modifications without amount limit
allow {
input.action == "add_to_cart"
}
package agent
default allow = false
# Allow during business hours
allow {
input.action == "submit_order"
time.clock(time.now_ns())[0] >= 9
time.clock(time.now_ns())[0] < 18
}
package agent
default allow = false
# Premium users can access all features
allow {
input.user.tier == "premium"
}
# Standard users limited to basic actions
allow {
input.user.tier == "standard"
input.action == "read"
}
The authors would like to thank Brian Campbell for his valuable feedback and insightful discussions during the development of this specification. His contributions helped shape key design decisions.¶