RFC 9126 — Pushed Authorization Requests — Versola Docs
/docs
Pre-1.00.7.5versola.ioGitHub

RFC 9126 — Pushed Authorization Requests

OAuth 2.0 Pushed Authorization Requests (PAR)

Specification: RFC 9126

Pushed Authorization Requests let a client send the authorization request payload directly to the authorization server over an authenticated back-channel call and receive a request_uri in exchange. Only that reference travels through the user agent, so the request cannot be inspected or tampered with in transit and is not limited by URL length.

Status

Partially implemented. Checked claims: 15 of 17.

Pushed Authorization Request Endpoint

  • POST /par — accepts application/x-www-form-urlencoded authorization request parameters
  • Client authentication — same methods as the token endpoint (client_secret_basic, client_secret_post, private_key_jwt per RFC 7523, and tls_client_auth and self_signed_tls_client_auth per RFC 8705)
  • request_uri parameter rejected in a pushed request (PushedAuthorizationSpec)
  • Full authorization request validation before any user interaction, including code_challenge_method=plain being refused
  • 201 Created with Cache-Control: no-store, and a 401 with WWW-Authenticate when client authentication fails
  • 405 Method Not Allowed with an Allow: POST header for anything but POST (PushedAuthorizationSpec)
  • 413 Content Too Large for bodies over 8 KiB (par.max-request-size, default 8192 bytes), checked before the body is parsed
  • 429 Too Many Requests — per-client rate limiting is not implemented
  • request parameter (JAR request objects, RFC 9101) — a client can push a signed request object instead of plain form parameters

client_id is required in the pushed request body and must identify the authenticated client.

Example

POST /par HTTP/1.1
Host: id.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

response_type=code&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20profile&state=af0ifjsldkj
&code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U
&code_challenge_method=S256
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store

{
  "request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
  "expires_in": 60
}

The request_uri reference carries 256 bits of entropy and is valid for 60 seconds by default (configurable with par.request-uri-ttl). Only a keyed hash of the reference is stored, so pushed requests cannot be replayed from a database dump alone.

Authorization Request

  • request_uri parameter at /authorize — replaces the pushed payload in full; the client_id is still required alongside it
  • request_uri_parameter_supported: true in discovery, which means pushed references only; a client-hosted URL is refused
  • Bound to the client that pushed it — a mismatching client_id is rejected
  • Single use — the reference is consumed when the authorization request is processed (PushedAuthorizationSpec)
  • Expired references are rejected

Parameters sent alongside request_uri at the authorization endpoint are ignored; the pushed payload is authoritative.

Error Response

Errors use the token endpoint format from RFC 6749 §5.2. Because a pushed request is processed before any user interaction, validation failures that would normally be redirected back to the client are returned directly in the response body:

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
  "error": "invalid_request",
  "error_description": "The request_uri parameter must not be provided to the pushed authorization request endpoint"
}

Authorization Server Metadata

  • pushed_authorization_request_endpoint — advertised in the server metadata document
  • require_pushed_authorization_requests — not implemented as server metadata; the requirement is registered per client (see below), not declared for the deployment

Client Metadata

  • require_pushed_authorization_requests (§6.2) — a client registered with it gets invalid_request when its request reaches /authorize without a request_uri (PushedAuthorizationSpec)

Not Implemented

  • Per-authorization-request redirect URIs (RFC 9126 §2.4) — redirect_uri must still exactly match one registered for the client
  • Rate limiting with 429 Too Many Requests

On a fapi2 tenant, pushed requests are mandatory for every client that has a redirect URI; see FAPI 2.0.

Where to look

The OpenAPI reference has the PAR specification, and Security profiles says when PAR is mandatory.