Skip to content
Ashish.
All posts
Diagram illustrating the shift from flat OAuth scopes to structured Rich Authorization Requests.
10 min readBackendIntermediateFeatured#oauth2#rar#rfc9396#fine-grained-authorization#security#api-access

Understanding OAuth 2.0 Rich Authorization Requests (RAR)

An examination of RFC 9396 and Rich Authorization Requests (RAR) for fine-grained authorization in OAuth 2.0.

By Ashish SrivastavaPart 1 of OAuth 2.0 & OIDC Mastery Series

The fundamental friction in modern OAuth 2.0 deployments lies not in the authentication mechanism, but in the granularity of the consent dialog. When a user logs into a third-party application, they are typically asked to grant permission for a broad set of actions, such as "read your email" or "access your files." This binary approach—granting a scope like email or denying it entirely—forces the user to trust the application implicitly for all resources covered by that scope. If an application requests contacts:read, the user cannot easily distinguish between accessing their primary contact list versus a specific folder of sensitive documents. RFC 9396, titled "Rich Authorization Requests," addresses this by introducing a mechanism where the client explicitly describes the specific resources it intends to access, shifting the burden of ambiguity from the user to the protocol.

The Mechanism of Standard Limitation

To understand why OAuth2 RAR is necessary, we must look at how the standard authorization request works under RFC 6749. In a typical flow, the client constructs a request URI containing parameters like client_id, redirect_uri, and scope. The scope parameter is a space-delimited string of tokens (e.g., profile email). The Authorization Server (AS) receives this string and maps it to a set of permissions. Crucially, the AS does not know which instances of the data the client needs.

Consider a scenario involving a project management tool (Client A) and a cloud storage provider (AS). Client A requests storage:read. Without RAR, the AS presents a consent screen asking, "Allow Client A to read your storage?" The user has no mechanism to say, "Allow reading only the /invoices/2023 folder, but deny access to /private/personal." The standard resource parameter, introduced in RFC 8705, attempts to address this by pointing to a specific resource URI, but it lacks the expressiveness to define complex relationships or multiple distinct resources within a single request. The AS is left guessing the intent, often defaulting to the broadest possible interpretation to ensure functionality, which increases the risk of data leakage.

Technical diagram comparing standard OAuth 2.0 flat scope strings versus Rich Authorization Requests JSON structure, showing a client sending a request with specific resource URIs nested inside the scope object, clean vector style, blue and gray palette, white background.

The RAR Structure and Resource Identification

RFC 9396 resolves this by redefining the scope parameter. Instead of a simple string, the scope parameter in a RAR request becomes a JSON object. This object allows the client to nest specific resource identifiers alongside the requested scopes. The mechanism relies on the concept of "resource sets." The client constructs a payload where each entry defines a resource (via a URI or identifier) and the specific scopes applicable to that resource.

Imagine the same project management tool (Client A) now needs to read invoices from the cloud storage provider. With RAR, Client A sends a request where the scope parameter is a JSON array of objects. Each object contains a resource field pointing to a specific URI, such as https://storage.example.com/invoices/2023, and a scope field listing the specific actions, like read. The AS receives this structured data and can render a consent screen that explicitly states: "Allow Client A to read files in /invoices/2023."

{
  "resource": "https://storage.example.com/invoices/2023",
  "scope": "read"
}

Note: In the actual authorization endpoint query string, this JSON object is URL-encoded and assigned to the scope parameter (e.g., scope=%7B%22resource%22...%7D). It is not a flat JSON object containing client_id and redirect_uri at the root level; those remain standard query parameters.

This structure allows the AS to parse the request and determine exactly which resource boundaries the user is consenting to. The AS is not forced to guess; it simply validates the resource URIs against its policy and presents the specific constraints to the user. This mechanism effectively decouples the "permission" (scope) from the "data" (resource) in the request phase, allowing them to be bound together only at the point of user consent.

The Authorization Flow and Token Binding

The flow proceeds similarly to standard OAuth 2.0, but the internal processing differs significantly. When the AS receives the RAR payload, it performs a parsing step defined in Section 3 of RFC 9396. The server validates that the resource URIs are well-formed and that the client is authorized to request access to those specific resources. If the AS supports RAR, it generates a consent UI that lists the specific resources. The user approves or denies these specific items.

Upon approval, the AS issues an Access Token. The critical mechanism here is how the token reflects the request. In a standard flow, the token might carry a scope string like storage:read. In a RAR flow, the token may include a "resource" claim or be bound to the specific resource identifiers requested. However, it is important to clarify that RFC 9396 primarily focuses on the request mechanism and does not mandate a specific 'resource' claim in the Access Token response. The token format is often determined by RFC 8705 or custom JWT claims defined by the implementation. The resource server (RS) receiving the token can then validate that the token's scope matches the requested resource, enforcing the fine-grained policy for api-access endpoints.

If the client attempts to access a resource outside the scope of the RAR request later, the RS will reject the request. For example, if Client A receives a token for reading /invoices/2023 and then tries to read /private/personal, the RS checks the token's metadata (which reflects the RAR constraints) and denies the access. This prevents the "scope creep" common in traditional OAuth implementations where a broad scope granted once is used indefinitely for all data types.

Implementation Tradeoffs

Implementing OAuth 2.0 advanced features like RAR introduces complexity that organizations must weigh against the security benefits. The primary tradeoff is the engineering effort required on the Authorization Server side. The AS must be capable of parsing JSON payloads within the scope parameter, validating resource URIs, and rendering dynamic consent UIs that display specific resource paths rather than generic permission names. This is not a trivial change for legacy systems that rely on simple string matching for scopes.

Furthermore, the ecosystem support is still maturing. Many existing Identity Providers (IdPs) and resource servers do not yet fully support RAR out of the box. Organizations adopting RAR must often build custom middleware or upgrade their IdP infrastructure. However, the security tradeoff favors adoption. By enabling fine-grained consent, RAR significantly reduces the attack surface. If a client application is compromised, the attacker gains access only to the specific resources listed in the RAR request, not the entire dataset associated with a broad scope. This aligns with the principle of least privilege at the protocol level.

The decision to adopt RAR should be driven by the sensitivity of the data and the complexity of the resource hierarchy. For applications dealing with simple, flat data structures, standard OAuth 2.0 may suffice. For systems managing complex, hierarchical data with strict privacy requirements, RAR provides the necessary mechanism to enforce precise access control. It transforms the authorization request from a vague promise of access into a concrete contract of limited privilege.

Common Pitfalls

When implementing Rich Authorization Requests, developers frequently encounter specific hurdles that can undermine the security benefits if not addressed correctly.

  1. Misinterpreting the 'resource' attribute: A common error is treating the resource attribute inside the RAR JSON scope as a standard OAuth query parameter. Unlike RFC 8705, which defines resource as a top-level query parameter, RAR embeds resource within the JSON value of the scope parameter. Confusing these two structures leads to malformed requests that the AS will reject.
  2. Failing to URL-encode the JSON scope value: Because the scope parameter in a RAR request is a JSON object, it must be strictly URL-encoded before being appended to the authorization URI. Failure to encode special characters (like {, }, :, /) results in broken URIs or parsing errors on the server side.
  3. Assuming token claims automatically include resource identifiers: Implementers often assume that issuing a token based on a RAR request automatically populates the token with resource information. As noted, RFC 9396 does not mandate specific token claims. Developers must explicitly configure their token issuance logic to include the relevant resource claims if downstream API validation relies on them.

Practical Takeaways

To successfully leverage Rich Authorization Requests, adopt the following mental models and rules:

  • RAR shifts granularity from scope to resource: Do not rely solely on scope strings for access control. Use RAR to bind specific permissions to specific resource URIs, allowing users to consent to "Read Invoice A" rather than "Read All Files."
  • JSON scope values must be URL-encoded: Always treat the JSON structure defining the scopes as a string value. Ensure your client library handles the encoding of the JSON object into the scope query parameter correctly.
  • Token claims are downstream implementation details: Understand that the protocol defines the request, not the response. You must explicitly configure your Authorization Server to emit the necessary resource claims in the Access Token if you intend to enforce restrictions at the Resource Server.

FAQ

Q: Is RFC 9396 compatible with existing Identity Providers? A: While the OAuth 2.0 core is widely supported, full RAR support (RFC 9396) is not yet universal in all commercial or open-source IdPs. Many providers offer partial support or require custom configuration. Organizations should verify their IdP's specific capabilities before planning a migration.

Q: How does RFC 9396 differ from RFC 8705? A: RFC 8705 (OAuth 2.0 Resource Indicators) introduces a top-level resource query parameter to indicate a single resource. RFC 9396 (Rich Authorization Requests) introduces a structured JSON scope parameter that allows for multiple resources, complex relationships, and finer-grained scope definitions within a single request. They can be used together, but RAR provides significantly more expressiveness.

Q: Should we adopt RAR immediately for all new projects? A: Adoption depends on the complexity of your data model. If your application deals with simple, flat data where standard scopes suffice, the engineering overhead of RAR may not be justified. However, for applications handling sensitive, hierarchical, or multi-tenant data, RAR is the recommended approach for fine-grained consent.

Conclusion

Rich Authorization Requests represent a necessary evolution of the OAuth 2.0 protocol, moving it from a system of broad trust to one of specific, verifiable consent. By allowing clients to describe exactly which resources they need and what actions they require on those resources, RFC 9396 empowers users to make informed decisions about their data. While the implementation requires careful architectural planning and infrastructure updates, the resulting security posture offers enhanced protection against over-permissioning. As the ecosystem matures, RAR will likely become the standard for any application handling sensitive or granular data, ensuring that the "read" permission is always tied to a specific, understood context.

Related posts