Scopes are strings such as payments. They cannot express “transfer 45 EUR from account A to account B once” or “read the lab results of patient 123 for the next week”. Rich Authorization Requests (RAR, RFC 9396) add the authorization_details parameter: a JSON array of structured permission objects.
The structure
Each object has a required type, which defines its schema, plus fields. RFC 9396 defines common optional fields:
| Field | Meaning | Example |
|---|---|---|
type | Required. Identifier of the authorization type. | payment_initiation |
locations | Resource servers or URIs where the permission applies. | ["https://payments.example.test"] |
actions | Actions allowed. | ["initiate", "status", "cancel"] |
datatypes | Kinds of data requested. | ["contacts", "photos"] |
identifier | A specific resource. | "account-12345" |
privileges | Privilege levels. | ["admin"] |
The type owner defines additional fields such as amounts or creditor details.
An example
[
{
"type": "payment_initiation",
"locations": ["https://payments.example.test"],
"instructedAmount": { "currency": "EUR", "amount": "45.00" },
"creditorName": "Merchant A",
"creditorAccount": { "iban": "DE02100100109307118603" },
"remittanceInformationUnstructured": "Order 1234"
}
]
The client sends this URL-encoded in authorization_details on the authorization request, preferably through PAR because it can be large and must not be tampered with.
Through the flow
- Authorization request: the client includes
authorization_details. - Consent: the authorization server shows the user what exactly is being approved, for example “Pay 45.00 EUR to Merchant A”. Rendering each type clearly is the server’s responsibility.
- Token response: the server returns the granted
authorization_details, which can be narrower than requested. - Access token: the details appear as a claim in JWT access tokens or in the introspection response.
- Resource server: the API enforces them: it executes only the approved payment.
RAR and scopes together
RAR does not replace scopes. Use scopes for coarse, long-lived access (openid, profile, accounts.read) and authorization_details for transactional or per-resource grants. A request can contain both.
Typical use cases
- Payment initiation and account access in open banking.
- Signing a specific document with a qualified signature service.
- Access to a specific patient’s records for a limited time in health care.
- Delegating a bounded task to an AI agent: “book one flight under 300 EUR for these dates”.
Design considerations
- Publish the JSON schema for each
typeand validate requests against it. - Advertise supported types in
authorization_details_types_supported(authorization server metadata and Protected Resource Metadata). - Decide how the server derives policy from details: amount limits, account ownership, risk scoring, step-up.
- Avoid making tokens long-lived when they carry transactional authorizations.