Skip to content
Ashish.
All posts
Diagram illustrating the Pushed Authorization Request (PAR) flow with request_uri.
6 min readDevelopmentBackend Developers, Security EngineersFeatured#oauth 2.0#rfc 9126#par#pushed authorization requests#request_uri#fapi#security#backend

RFC 9126: Pushed Authorization Requests

An examination of RFC 9126 Pushed Authorization Requests (PAR) for OAuth 2.0, detailing how request_uri enhances security and performance for backend developers.

By Ashish KumarPart 5 of OAuth 2.0 RFCs Every Engineer Should Read

This article is Part 5 of the "OAuth 2.0 RFCs Every Engineer Should Read" series.

For backend engineers managing OAuth 2.0 flows, the Authorization Code Grant is the standard workhorse. However, the traditional implementation of this grant type carries a structural flaw: it forces sensitive configuration data into the URL query string. This design choice creates security vulnerabilities related to data leakage and performance issues due to URL length limits. RFC 9126, titled "Pushed Authorization Requests" (PAR), introduces a mechanism to move these parameters off the URL and into the body of a server-to-server request, returning a temporary reference ID. This shift is not merely an optimization; it is a foundational requirement for modern security profiles like FAPI 2.0.

The Vulnerability of URL-Based Parameters

In a standard OAuth 2.0 authorization request, the client application constructs a URL directed at the Authorization Server (AS). This URL contains critical parameters in the query string:

https://auth.example.com/authorize?
  response_type=code&
  client_id=abc123&
  scope=openid%20profile&
  redirect_uri=https://app.example.com/callback&
  state=random_state_value

While this works for simple integrations, it exposes the system to several mechanisms of failure.

First, URLs are logged extensively. Web server access logs, proxy logs, browser history, and network monitoring tools often capture the full URL. If the client_id or other parameters are sensitive, or if the state parameter is predictable, an attacker with access to these logs can perform session fixation or infer application architecture. Second, URLs are subject to length limits. While browsers handle long URLs reasonably well, many intermediaries—such as load balancers, firewalls, and reverse proxies—have strict URI length limits, commonly 8KB or less. A request exceeding these limits is dropped, causing a denial of service for legitimate users.

A clean, technical architectural diagram showing the standard OAuth 2.0 authorization code flow with parameters exposed in the browser URL bar. Use a muted color palette with red highlights on the URL parameters to indicate security risk. Style : minimalist vector illustration.

The PAR Mechanism

RFC 9126 redefines how the authorization request is initiated. Instead of constructing a massive URL, the client application makes a direct HTTP POST request to a new endpoint on the Authorization Server: /pushed_authorization_request.

This endpoint accepts the same parameters that would have gone into the URL, but they are transmitted in the request body using the application/x-www-form-urlencoded format.

POST /pushed_authorization_request HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64_encoded_client_credentials>
 
response_type=code&
client_id=abc123&
scope=openid%20profile&
redirect_uri=https://app.example.com/callback&
state=random_state_value

The Authorization Server validates the client credentials, parses the parameters, stores the request data internally, and generates a unique, opaque identifier. It then returns a JSON response containing a request_uri and an expiration time.

HTTP/1.1 201 Created
Content-Type: application/json
 
{
  "request_uri": "urn:ietf:params:oauth:request_uri:837492",
  "expires_in": 60
}

The request_uri is a URI that references the stored request. The expires_in field indicates the lifetime of this reference in seconds, typically ranging from 30 to 60 seconds. This short TTL is a critical security feature, limiting the window of opportunity for an attacker to reuse the reference if it is intercepted.

Redirecting with the Reference

Once the client receives the request_uri, it redirects the user agent (the browser) to the AS’s /authorize endpoint. However, instead of passing all the parameters in the query string, it passes only the client_id and the request_uri parameter.

GET /authorize?client_id=abc123&request_uri=urn:ietf:params:oauth:request_uri:837492

The Authorization Server receives this request. It extracts the request_uri, looks up the corresponding stored request data in its database or cache, and validates that the request has not expired. If valid, the AS treats the stored parameters as if they had been provided directly in the URL. The authentication flow proceeds normally: the user logs in, consents to the scopes, and is redirected back to the redirect_uri with an authorization code.

Security and Performance Implications

The primary security benefit of PAR is the elimination of sensitive data from the URL. Since the request_uri is opaque and short-lived, it cannot be used to reconstruct the original request parameters after it expires. Furthermore, because the parameters are never placed in the browser history, they are immune to logging vulnerabilities in intermediate proxies that might log full URLs.

This mechanism also enables the enforcement of strict security policies. For example, the Financial-grade API (FAPI) 2.0 specification mandates the use of PAR for all financial transactions. FAPI 2.0 mandates PAR, which allows the AS to validate parameters like redirect_uri before user interaction. By moving the validation to the /pushed_authorization_request step, the AS can reject invalid or malicious requests before any user interaction occurs, reducing the attack surface for phishing and redirect-based attacks.

From a performance perspective, PAR reduces the size of the initial redirect. While this is minor in terms of bandwidth, it ensures that the redirect URL remains within safe length limits for all intermediaries. Additionally, by offloading the parsing and validation of complex scopes and client configurations to the AS during the push phase, the client application can simplify its redirect logic, reducing the likelihood of client-side implementation errors.

Implementation Considerations

Implementing PAR requires changes to both the client and the Authorization Server. The client must support the /pushed_authorization_request endpoint and handle the asynchronous delay between pushing the request and redirecting the user. This delay is typically negligible (under 1 second), but it must be accounted for in the user experience design.

The Authorization Server must implement the new endpoint, store the request data securely, and ensure that the request_uri is invalidated after the specified expiration time. It must also validate that the request_uri is used only once, preventing replay attacks.

For backend developers, adopting PAR is a step toward aligning with industry best practices. The trend is clear: move sensitive data out of the URL and into secure, server-managed channels. RFC 9126 provides the standard mechanism for this transition, offering a foundation for secure, scalable authentication flows.

Conclusion

RFC 9126 Pushed Authorization Requests is not just an incremental improvement; it is a structural correction to OAuth 2.0’s original design. By decoupling the authorization request parameters from the browser redirect, PAR eliminates significant security risks associated with URL logging and length limits. For backend engineers, implementing PAR is essential for achieving compliance with modern security standards like FAPI 2.0 and for building resilient, secure authentication systems. The mechanism is straightforward: push the data, get the reference, redirect with the reference. This simple shift significantly enhances the security posture of any OAuth 2.0 integration.

Related posts