RFC 9126

OAuth 2.0 Pushed Authorization Requests

๐Ÿ“… published September 2021, from ietf

RFC 9126 ๐Ÿ’– OAuth 2.0 Pushed Authorization Requests

Okay bestie, here's the full vibe check ๐ŸŽ€. This is RFC 9126, called "OAuth 2.0 Pushed Authorization Requests." The authors are T. Lodderstedt (yes.com), B. Campbell (Ping Identity), N. Sakimura (NAT.Consulting), D. Tonge (Moneyhub Financial Technology), and F. Skokan (Auth0). It's a Standards Track document, ISSN 2070-1721, dated September 2021 โœจ. The title block doesn't list anything it obsoletes or updates, so there's nothing extra to check there ๐Ÿซถ.

Abstract ๐ŸŒธ

So this doc defines the pushed authorization request (PAR) endpoint ๐Ÿ’…. It lets clients push the whole payload of an OAuth 2.0 authorization request straight to the authorization server with a direct request. In return, the client gets a request URI, which is basically a claim ticket that points to that data for the next call to the authorization endpoint ๐Ÿฆ‹.

Status of This Memo ๐ŸŒˆ

This is an Internet Standards Track document โญ.

This document is a product of the Internet Engineering Task Force (IETF) ๐ŸŒธ. It represents the consensus of the IETF community. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 7841 ๐Ÿงš.

Info about the current status of this document, any errata, and how to send feedback on it lives at https://www.rfc-editor.org/info/rfc9126 ๐Ÿ’œ.

Copyright (c) 2021 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) as in effect on the date this document was published. Please read these carefully, because they spell out your rights and restrictions for this document ๐Ÿ™ˆ. Code Components extracted from this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License ๐Ÿ’….

Table of Contents ๐Ÿ“

1.  Introduction
  1.1.  Introductory Example
  1.2.  Conventions and Terminology
2.  Pushed Authorization Request Endpoint
  2.1.  Request
  2.2.  Successful Response
  2.3.  Error Response
  2.4.  Management of Client Redirect URIs
3.  The "request" Request Parameter
4.  Authorization Request
5.  Authorization Server Metadata
6.  Client Metadata
7.  Security Considerations
  7.1.  Request URI Guessing
  7.2.  Open Redirection
  7.3.  Request Object Replay
  7.4.  Client Policy Change
  7.5.  Request URI Swapping
8.  Privacy Considerations
9.  IANA Considerations
  9.1.  OAuth Authorization Server Metadata
  9.2.  OAuth Dynamic Client Registration Metadata
  9.3.  OAuth URI Registration
10. References
  10.1.  Normative References
  10.2.  Informative References
Acknowledgements
Authors' Addresses

1. Introduction ๐Ÿฆ‹

This document defines the pushed authorization request (PAR) endpoint, and it lets an OAuth [RFC6749] client push the payload of an authorization request directly to the authorization server ๐Ÿ’–. The client gets a request URI value back in exchange. Later, it uses that value to point to the authorization request payload in a follow-up call to the authorization endpoint through the user agent โœจ.

Okay so in OAuth [RFC6749], authorization request parameters usually get sent as URI query parameters through redirection in the user agent. It's simple, but it brings some problems ๐Ÿ˜ญ:

  • There's no cryptographic integrity and authenticity protection ๐Ÿ”. An attacker could, for example, change the scope of access being requested, or swap out the context of a payment transaction by changing scope values. Protocol features do exist that help clients or users catch some of these changes, but stopping modifications early in the process is a much more robust fix ๐Ÿ’….
  • There's no mechanism to make sure the request parameters stay confidential ๐Ÿ™ˆ. HTTPS is required for the authorization endpoint, but the request data still passes through the user agent in the clear, and query string data can leak into web server logs and to other sites through the referrer. That leakage can be a big deal if personally identifiable information or other regulated data is in the authorization request, which is pretty likely in identity, open banking, and similar scenarios ๐Ÿ˜ญ.
  • Authorization request URLs can get really long, especially in scenarios that need fine-grained authorization data, and that can cause errors when the request gets processed ๐Ÿ’€.

JWT-Secured Authorization Request (JAR) [RFC9101] fixes the security problems by letting OAuth clients wrap authorization request parameters in a Request Object. That's a signed and optionally encrypted JSON Web Token (JWT) [RFC7519] ๐Ÿงš. To handle the size limits, JAR adds the "request_uri" parameter, which lets clients send a reference to a Request Object instead of the Request Object itself ๐ŸŒˆ.

This document works alongside JAR by giving clients an interoperable way to push the payload of an authorization request straight to the authorization server. In return, they get a "request_uri" value they can use at the authorization server in a later authorization request ๐ŸŽ€.

PAR helps OAuth security by giving clients a simple way to make a confidential, integrity-protected authorization request โญ. Clients that need an even higher security level, especially cryptographically confirmed non-repudiation, can use JWT-based Request Objects as defined by [RFC9101] together with PAR ๐Ÿ‘‘.

PAR also lets the authorization server authenticate the client before any user interaction happens ๐Ÿซถ. Because the server knows who the client is earlier in the process, it can turn down illegitimate requests much sooner. That makes it harder to spoof clients or tamper with or misuse an authorization request ๐Ÿ›ก๏ธ.

Note that HTTP "POST" requests to the authorization endpoint through the user agent, as described in Section 3.1 of [RFC6749] and Section 3.1.2.1 of [OIDC], could also help with the request size limits above. However, that's only optional per [RFC6749]. Even when it's supported, it's a viable option for conventional web applications but is prohibitively difficult to use with installed mobile applications ๐Ÿ“ฑ. As described in [RFC8252], those apps use platform-specific APIs to open the authorization request URI in the system browser. When a mobile app launches a browser, though, the first request is limited to the "GET" method ๐Ÿ˜ค. Using "POST" for the authorization request would mean the app first has to send the browser to a URI it controls via "GET", somehow carry the big authorization request payload along, and then have the response contain the content and script that starts a cross-site form "POST" to the authorization server. Way too much drama ๐Ÿ’€. PAR is simpler to use and has the extra security benefits described above, so it's the move ๐Ÿ’….

1.1. Introductory Example ๐ŸŒธ

In conventional OAuth 2.0, a client usually starts an authorization request by telling the user agent to make an HTTP request like this one to the authorization server's authorization endpoint (extra line breaks and indentation are just for display):

GET /authorize?response_type=code
 &client_id=CLIENT1234&state=duk681S8n00GsJpe7n9boxdzen
 &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: as.example.com

That same request could instead be pushed straight to the authorization server by the client, with a "POST" request to the PAR endpoint, like in this example (extra line breaks and spaces are just for display). The client can authenticate, for example with JWT client assertion-based authentication as shown, because the request goes directly to the authorization server ๐Ÿ”ฅ.

POST /as/par HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

&response_type=code
&client_id=CLIENT1234&state=duk681S8n00GsJpe7n9boxdzen
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_assertion_type=
 urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJraWQiOiI0MiIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJDTE
 lFTlQxMjM0Iiwic3ViIjoiQ0xJRU5UMTIzNCIsImF1ZCI6Imh0dHBzOi8vc2VydmVyL
 mV4YW1wbGUuY29tIiwiZXhwIjoxNjI1ODY4ODc4fQ.Igw8QrpAWRNPDGoWGRmJumLBM
 wbLjeIYwqWUu-ywgvvufl_0sQJftNs3bzjIrP0BV9rRG-3eI1Ksh0kQ1CwvzA

The authorization server replies with a request URI ๐Ÿงš:

HTTP/1.1 201 Created
Cache-Control: no-cache, no-store
Content-Type: application/json

{
  "request_uri": "urn:example:bwc4JK-ESC0w8acc191e-Y1LTC2",
  "expires_in": 90
}

The client uses that request URI value to build the follow-up authorization request. It does this by telling the user agent to make an HTTP request to the authorization server's authorization endpoint, like this (extra line breaks and indentation are just for display) ๐ŸŽ€:

GET /authorize?client_id=CLIENT1234
 &request_uri=urn%3Aexample%3Abwc4JK-ESC0w8acc191e-Y1LTC2 HTTP/1.1
Host: as.example.com

1.2. Conventions and Terminology ๐ŸŒˆ

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, as shown here ๐Ÿ“šโœจ.

This specification uses the terms "access token", "authorization server", "authorization endpoint", "authorization request", "token endpoint", and "client" as defined by "The OAuth 2.0 Authorization Framework" [RFC6749] ๐Ÿ’œ.

2. Pushed Authorization Request Endpoint โœจ

okay bestie, so the PAR endpoint is an HTTP API that lives at the authorization server ๐ŸŽ€ It takes HTTP "POST" requests and carries the parameters in the request body, formatted as "application/x-www-form-urlencoded". That format uses UTF-8 as its character encoding, as explained in Appendix B of [RFC6749] ๐Ÿ’… And the PAR endpoint URL MUST use the "https" scheme ๐Ÿ”’ no plain http allowed, periodt ๐Ÿ’€

Authorization servers that support PAR SHOULD list the URL of their pushed authorization request endpoint in their authorization server metadata document [RFC8414], using the "pushed_authorization_request_endpoint" parameter that's defined in Section 5 ๐Ÿฆ‹

The endpoint takes the authorization request parameters defined in [RFC6749] for the authorization endpoint, plus all the applicable extensions for that endpoint. Some examples are Proof Key for Code Exchange (PKCE) [RFC7636], Resource Indicators [RFC8707], and OpenID Connect (OIDC) [OIDC] ๐Ÿงš The endpoint MAY also support sending the set of authorization request parameters as a Request Object according to [RFC9101] and Section 3 of this document ๐ŸŒˆ

The client authentication rules from [RFC6749] for token endpoint requests, including the applicable authentication methods, apply to the PAR endpoint too ๐Ÿซถ If it applies, the "token_endpoint_auth_method" client metadata parameter [RFC7591] tells you which registered authentication method the client should use when it makes direct requests to the authorization server, including requests to the PAR endpoint. Similarly, the "token_endpoint_auth_methods_supported" authorization server metadata [RFC8414] parameter lists the client authentication methods the authorization server supports when it accepts direct requests from clients, including requests to the PAR endpoint โœจ

Due to historical reasons, there's a bit of ambiguity about which audience value to use when you're doing JWT client assertion-based authentication ๐Ÿ˜ญ (defined in Section 2.2 of [RFC7523] with "private_key_jwt" or "client_secret_jwt" authentication method names per Section 9 of [OIDC]). To clear that up, the issuer identifier URL of the authorization server according to [RFC8414] SHOULD be used as the value of the audience. For interoperability's sake, the authorization server MUST accept its issuer identifier, its token endpoint URL, or its pushed authorization request endpoint URL as values that identify it as an intended audience ๐Ÿ”ฅ

2.1. Request

A client sends the parameters that make up an authorization request directly to the PAR endpoint ๐Ÿ“ฎ A typical parameter set might include "client_id", "response_type", "redirect_uri", "scope", "state", "code_challenge", and "code_challenge_method", like in the example below. But honestly, the pushed authorization request can be built from any of the parameters that work at the authorization endpoint, including the ones defined in [RFC6749] and all the applicable extensions ๐Ÿ’– The one exception is the "request_uri" authorization request parameter, which MUST NOT be provided ๐Ÿ™ˆ

The request can also include any extra parameters the client needs for authentication, like "client_secret" or "client_assertion" and "client_assertion_type", as appropriate for that client. These parameters are defined and registered for the token endpoint, but they only apply to client authentication. When they show up in a pushed authorization request, they're only used for client authentication and have nothing to do with the authorization request itself ๐Ÿฆ‹ Any token endpoint parameters that aren't related to client authentication have no defined meaning in a pushed authorization request. The "client_id" parameter means the same thing for both authorization requests and token endpoint requests. Since it's a required authorization request parameter, it's also required in a pushed authorization request ๐ŸŒธ

The client builds the message body of its HTTP "POST" request with parameters formatted as "x-www-form-urlencoded", using UTF-8 as the character encoding, as described in Appendix B of [RFC6749]. If it applies, the client also adds its authentication credentials to the request header or the request body, following the same rules as for token endpoint requests ๐ŸŽ€

Here's the example, with extra line breaks in the message body just so it's easier to read (they're not part of the actual message) ๐Ÿ‘€

POST /as/par HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

response_type=code&state=af0ifjsldkj&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&code_challenge=K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U
&code_challenge_method=S256&scope=account-information
&client_assertion_type=
 urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJraWQiOiJrMmJkYyIsImFsZyI6IlJTMjU2In0.eyJpc3Mi
 OiJzNkJoZFJrcXQzIiwic3ViIjoiczZCaGRSa3F0MyIsImF1ZCI6Imh0dHBzOi8vc
 2VydmVyLmV4YW1wbGUuY29tIiwiZXhwIjoxNjI1ODY5Njc3fQ.te4IdnP_DK4hWrh
 TWA6fyhy3fxlAQZAhfA4lmzRdpoP5uZb-E90R5YxzN1YDA8mnVdpgj_Bx1lG5r6se
 f5TlckApA3hahhC804dcqlE4naEmLISmN1pds2WxTMOUzZY8aKKSDzNTDqhyTgE-K
 dTb3RafRj7tdZb09zWs7c_moOvfVcQIoy5zz1BvLQKW1Y8JsYvdpu2AvpxRPbcP8W
 yeW9B6PL6_fy3pXYKG3e-qUcvPa9kan-mo9EoSgt-YTDQjK1nZMdXIqTluK9caVJE
 RWW0fD1Y11_tlOcJn-ya7v7d8YmFyJpkhZfm8x1FoeH0djEicXTixEkdRuzsgUCm6
 GQ

The authorization server MUST process the request like this ๐Ÿง 

  1. Authenticate the client the same way it does at the token endpoint (Section 2.3 of [RFC6749]).
  2. Reject the request if the "request_uri" authorization request parameter is provided ๐Ÿšซ
  3. Validate the pushed request the same way it would validate an authorization request sent to the authorization endpoint. For example, the authorization server checks whether the redirect URI matches one of the redirect URIs configured for the client, and also checks whether the client is authorized for the scope it's asking for. This validation lets the authorization server refuse unauthorized or fraudulent requests early ๐Ÿ˜ค The authorization server MAY omit validation steps it can't perform while processing the pushed request; however, those checks MUST then be performed when the authorization request gets processed at the authorization endpoint ๐Ÿ”

The authorization server MAY allow clients with authentication credentials to set up per-authorization-request redirect URIs with every pushed authorization request ๐ŸŒˆ This is explained in more detail in Section 2.4. It's possible because, unlike [RFC6749], this specification lets the authorization server authenticate clients and validate their requests before the actual authorization request happens. Main character energy ๐Ÿ‘‘

2.2. Successful Response

If the verification succeeds, the server MUST generate a request URI and send it back in the response with a "201" HTTP status code ๐ŸŽ‰ The following parameters go in as top-level members of the HTTP response message body, using the "application/json" media type as defined by [RFC8259]:

request_uri : This is the request URI for the authorization request that was posted. It's a single-use reference to the matching request data in the later authorization request. How the authorization process actually gets that request data is up to the authorization server and is out of scope for this specification. There's no need to make the authorization request data available to anyone else through this URI ๐Ÿ”

expires_in : A JSON number for how long the request URI lasts, in seconds, as a positive integer. The lifetime is up to the authorization server, but it'll typically be pretty short (e.g., between 5 and 600 seconds) โณ

The format of the "request_uri" value is up to the authorization server, but it MUST contain some part generated with a cryptographically strong pseudorandom algorithm, so it's computationally infeasible to predict or guess a valid value (see Section 10.10 of [RFC6749] for the specifics) ๐Ÿ”ฅ The authorization server MAY construct the "request_uri" value using the form urn:ietf:params:oauth:request_uri:<reference-value>, where <reference-value> is the random part of the URI that references the matching authorization request data ๐Ÿฆ‹

The "request_uri" value MUST be bound to the client that posted the authorization request ๐Ÿซถ

Here's what that response looks like:

HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-cache, no-store

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

2.3. Error Response

The authorization server sends back an error response in the same format as the error responses from the token endpoint in Section 5.2 of [RFC6749], using the right error code from there or from Section 4.1.2.1 of [RFC6749] ๐Ÿ’€ In cases where Section 4.1.2.1 of [RFC6749] says no automatic redirect with an error back to the requesting client is allowed, so no error code gets defined (for example, when the request fails because the redirection URI is missing, invalid, or doesn't match), the "invalid_request" error code can be used as the default ๐Ÿ™ˆ Error codes defined by an OAuth extension can also be used if that extension was involved in the initial processing of the pushed authorization request. Since processing the pushed request doesn't involve any resource owner interaction, user-interaction error codes like "consent_required" from [OIDC] are never returned ๐Ÿ™…โ€โ™€๏ธ

If the client is required to use signed Request Objects, either by the authorization server or by the client policy (see [RFC9101], Section 10.5), the authorization server MUST only accept requests that match the definition in Section 3, and it MUST refuse any other request with HTTP status code 400 and error code "invalid_request" ๐Ÿšจ

On top of all that, the PAR endpoint can also use these HTTP status codes:

  • 405: If the request didn't use the "POST" method, the authorization server responds with an HTTP 405 (Method Not Allowed) status code ๐Ÿ™…
  • 413: If the request size went over the upper bound the authorization server allows, the authorization server responds with an HTTP 413 (Payload Too Large) status code ๐Ÿ“ฆ
  • 429: If the number of requests from a client in a particular time period goes over what the authorization server allows, the authorization server responds with an HTTP 429 (Too Many Requests) status code ๐Ÿข

Here's an example of an error response from the PAR endpoint:

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

{
  "error": "invalid_request",
  "error_description":
    "The redirect_uri is not valid for the given client"
}

2.4. Management of Client Redirect URIs โœจ

okay so OAuth 2.0 [RFC6749] lets clients use unregistered "redirect_uri" values in certain situations, and it lets the authorization server apply its own matching rules to the "redirect_uri" value the client sends to the authorization endpoint ๐ŸŽ€. BUT the OAuth security BCP [OAUTH-SECURITY-TOPICS] and the OAuth 2.1 spec [OAUTH-V2] both say the authorization server has to exactly match the "redirect_uri" parameter against the set of redirect URIs already set up for that client ๐Ÿ”’. Why? It's an early warning for client impersonation attempts, and it stops token leakage and open redirection ๐Ÿšจ. The catch is that client management gets kinda annoying, because the redirect URI is usually the most volatile part of a client's policy ๐Ÿ˜ฉ.

The exact matching requirement MAY be relaxed when PAR is used by clients that already have authentication credentials with the authorization server ๐Ÿ’–. This works because, unlike a normal authorization request, the authorization server authenticates the client before the authorization process even starts, so it knows it's talking to the legit client ๐Ÿซถ. The authorization server MAY let those clients send "redirect_uri" values that were never registered ๐Ÿฆ‹. That gives the client more flexibility (like minting distinct "redirect_uri" values per authorization server at runtime) and makes client management way simpler โœจ. It's totally up to the authorization server to put restrictions on the supplied "redirect_uri" values, e.g., the authorization server MAY require a certain URI prefix or allow only a query parameter to vary at runtime ๐Ÿ’….

๐Ÿ’Œ Note: Being able to set up transaction-specific redirect URIs is also a lifesaver when client IDs, their credentials, and their policies are managed by a trusted third party, e.g., via client certificates that contain client permissions. An externally managed client like that could talk to an authorization server that trusts the third party, without needing an extra registration step ๐Ÿงš

3. The "request" Request Parameter ๐ŸŽ€

Clients MAY use the "request" parameter, as defined in JAR [RFC9101], to push a Request Object JWT to the authorization server ๐Ÿ’œ. The rules for processing, signing, and encrypting the Request Object as defined in JAR [RFC9101] apply ๐Ÿ”. The request parameters a given client authentication method needs go in the "application/x-www-form-urlencoded" request directly, and they're the only parameters other than "request" in the form body (e.g., mutual TLS client authentication [RFC8705] uses the "client_id" HTTP request parameter, while JWT assertion-based client authentication [RFC7523] uses "client_assertion" and "client_assertion_type") ๐ŸŒธ. Everything else, meaning all the parameters about the authorization request itself, MUST appear as claims of the JWT that represents the authorization request ๐Ÿงพ.

Here's an example of a pushed authorization request using a signed Request Object, with the same authorization request payload as the example in Section 2.1 โœจ. The client is authenticated with JWT client assertion-based authentication [RFC7523] (extra line breaks and spaces are just for display ๐Ÿ‘€):

POST /as/par HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

client_assertion_type=
 urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJraWQiOiJrMmJkYyIsImFsZyI6IlJTMjU2In0.eyJpc3Mi
 OiJzNkJoZFJrcXQzIiwic3ViIjoiczZCaGRSa3F0MyIsImF1ZCI6Imh0dHBzOi8vc
 2VydmVyLmV4YW1wbGUuY29tIiwiZXhwIjoxNjI1ODY5Njc3fQ.te4IdnP_DK4hWrh
 TWA6fyhy3fxlAQZAhfA4lmzRdpoP5uZb-E90R5YxzN1YDA8mnVdpgj_Bx1lG5r6se
 f5TlckApA3hahhC804dcqlE4naEmLISmN1pds2WxTMOUzZY8aKKSDzNTDqhyTgE-K
 dTb3RafRj7tdZb09zWs7c_moOvfVcQIoy5zz1BvLQKW1Y8JsYvdpu2AvpxRPbcP8W
 yeW9B6PL6_fy3pXYKG3e-qUcvPa9kan-mo9EoSgt-YTDQjK1nZMdXIqTluK9caVJE
 RWW0fD1Y11_tlOcJn-ya7v7d8YmFyJpkhZfm8x1FoeH0djEicXTixEkdRuzsgUCm6
 GQ
&request=eyJraWQiOiJrMmJkYyIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJzNkJoZ
 FJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJleHAiOj
 E2MjU4Njk2NzcsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwiY2xpZW50X2lkIjoiczZ
 CaGRSa3F0MyIsInJlZGlyZWN0X3VyaSI6Imh0dHBzOi8vY2xpZW50LmV4YW1wbGUu
 b3JnL2NiIiwic2NvcGUiOiJhY2NvdW50LWluZm9ybWF0aW9uIiwic3RhdGUiOiJhZ
 jBpZmpzbGRraiIsImNvZGVfY2hhbGxlbmdlIjoiSzItbHRjODNhY2M0aDBjOXc2RV
 NDX3JFTVRKM2J3dy11Q0hhb2VLMXQ4VSIsImNvZGVfY2hhbGxlbmdlX21ldGhvZCI
 6IlMyNTYifQ.l9R3RC9bFBHry_8acObQjEf4fX5yfJkWUPfak3J3iiBm0aaQznPw5
 BZ0B3VQZ9_KYdPt5bTkaflS5fSDklM3_7my9MyOSKFYmf46INk6ju_qUuC2crkOQX
 ZWYJB-0bnYEbdHpUjazFSUvN49cEGstNQeE-dKDWHNgEojgcuNA_pjKfL9VYp1dEA
 6-WjXZ_OlJ7R_mBWpjFAzc0UkQwqX5hfOJoGTqB2tE4a4aB2z8iYlUJp0DeeYp_hP
 N6svtmdvte73p5bLGDFpRIlmrBQIAQuxiS0skORpXlS0cBcgHimXVnXOJG7E-A_lS
 _5y54dVLQPA1jKYx-fxbYSG7dp2fw
&client_id=s6BhdRkqt3

The authorization server MUST take the following steps on top of the processing rules defined in Section 2.1 ๐Ÿง :

  1. If applicable, decrypt the Request Object as specified in JAR [RFC9101], Section 6.1. ๐Ÿ”“
  2. Validate the Request Object signature as specified in JAR [RFC9101], Section 6.2. โœ…
  3. If the client has authentication credentials established with the authorization server, reject the request if the authenticated "client_id" does not match the "client_id" claim in the Request Object. Additionally, requiring the "iss" claim to match the "client_id" is at the discretion of the authorization server. ๐Ÿ•ต๏ธโ€โ™€๏ธ

The following RSA key pair, represented in JSON Web Key (JWK) format [RFC7517], can be used to validate or recreate the Request Object signature in the example above (extra line breaks and indentation within values are just for display ๐Ÿฅบ):

{
  "kty": "RSA",
  "kid":"k2bdc",
  "n": "y9Lqv4fCp6Ei-u2-ZCKq83YvbFEk6JMs_pSj76eMkddWRuWX2aBKGHAtKlE
        5P7_vn__PCKZWePt3vGkB6ePgzAFu08NmKemwE5bQI0e6kIChtt_6KzT5Oa
        aXDFI6qCLJmk51Cc4VYFaxgqevMncYrzaW_50mZ1yGSFIQzLYP8bijAHGVj
        dEFgZaZEN9lsn_GdWLaJpHrB3ROlS50E45wxrlg9xMncVb8qDPuXZarvghL
        L0HzOuYRadBJVoWZowDNTpKpk2RklZ7QaBO7XDv3uR7s_sf2g-bAjSYxYUG
        sqkNA9b3xVW53am_UZZ3tZbFTIh557JICWKHlWj5uzeJXaw",
  "e": "AQAB",
  "d": "LNwG_pCKrwowALpCpRdcOKlSVqylSurZhE6CpkRiE9cpDgGKIkO9CxPlXOL
        zjqxXuQc8MdMqRQZTnAwgd7HH0B6gncrruV3NewI-XQV0ckldTjqNfOTz1V
        Rs-jE-57KAXI3YBIhu-_0YpIDzdk_wBuAk661Svn0GsPQe7m9DoxdzenQu9
        O_soewUhlPzRrTH0EeIqYI715rwI3TYaSzoWBmEPD2fICyj18FF0MPy_SQz
        k3noVUUIzfzLnnJiWy_p63QBCMqjRoSHHdMnI4z9iVpIwJWQ3jO5n_2lC2-
        cSgwjmKsFzDBbQNJc7qMG1N6EssJUwgGJxz1eAUFf0w4YAQ",
  "qi": "J-mG0swR4FTy3atrcQ7dd0hhYn1E9QndN-
        -sDG4EQO0RnFj6wIefCvwIc4
        7hCtVeFnCTPYJNc_JyV-mU-9vlzS5GSNuyR5qdpsMZXUMpEvQcwKt23ffPZ
        YGaqfKyEesmf_Wi8fFcE68H9REQjnniKrXm7w2-IuG_IrVJA9Ox-uU",
  "q": "4hlMYAGa0dvogdK1jnxQ7J_Lqpqi99e-AeoFvoYpMPhthChTzwFZO9lQmUo
        BpMqVQTws_s7vWGmt7ZAB3ywkurf0pV7BD0fweJiUzrWk4KJjxtmP_auuxr
        jvm3s2FUGn6f0wRY9Z8Hj9A7C72DnYCjuZiJQMYCWDsZ8-d-L1a-s",
  "p": "5sd9Er3I2FFT9R-gy84_oakEyCmgw036B_nfYEEOCwpSvi2z7UcIVK3bSEL
        5WCW6BNgB3HDWhq8aYPirwQnqm0K9mX1E-4xM10WWZ-rP3XjYpQeS0Snru5
        LFVWsAzi-FX7BOqBibSAXLdEGXcXa44l08iec_bPD3xduq5V_1YoE",
  "dq": "Nz2PF3XM6bEc4XsluKZO70ErdYdKgdtIJReUR7Rno_tOZpejwlPGBYVW19
        zpAeYtCT82jxroB2XqhLxGeMxEPQpsz2qTKLSe4BgHY2ml2uxSDGdjcsrbb
        NoKUKaN1CuyZszhWl1n0AT_bENl4bJgQj_Fh0UEsQj5YBBUJt5gr_k",
  "dp": "Zc877jirkkLOtyTs2vxyNe9KnMNAmOidlUc2tE_-0gAL4Lpo1hSwKCtKwe
        ZJ-gkqt1hT-dwNx_0Xtg_-NXsadMRMwJnzBMYwYAfjApUkfqABc0yUCJJl3
        KozRCugf1WXkU9GZAH2_x8PUopdNUEa70ISowPRh04HANKX4fkjWAE"
}

4. Authorization Request ๐ŸŒท

The client uses the "request_uri" value that the authorization server returned to build an authorization request, as defined in [RFC9101] ๐Ÿช„. Here's an example where the client sends the user agent off to make this HTTP request (extra line breaks and indentation are for display only ๐Ÿ’ซ):

GET /authorize?client_id=s6BhdRkqt3&request_uri=urn%3Aietf%3Aparams
 %3Aoauth%3Arequest_uri%3A6esc_11ACC5bwc014ltc14eY22c HTTP/1.1
Host: as.example.com

Since parts of the authorization request content, e.g., the "code_challenge" parameter value, are unique to one particular authorization request, the client MUST only use a "request_uri" value once ๐Ÿ™…โ€โ™€๏ธ. Authorization servers SHOULD treat "request_uri" values as one-time use, but MAY allow duplicate requests because a user reloads or refreshes their user agent ๐Ÿ”„. An expired "request_uri" MUST be rejected as invalid ๐Ÿ’€.

The authorization server MUST validate authorization requests that come from a pushed request the same way it would validate any other authorization request ๐Ÿ”. The authorization server MAY skip validation steps it already did when the request was pushed, as long as it can confirm the request was a pushed request AND the request or the authorization server's policy hasn't been changed in a way that would affect the outcome of those skipped steps ๐Ÿง.

Authorization server policy MAY dictate, either globally or on a per-client basis, that PAR be the only way for a client to pass authorization request data ๐Ÿšช. In that case, the authorization server will refuse to process any request to the authorization endpoint that doesn't have a "request_uri" parameter with a value obtained from the PAR endpoint, and it will use the "invalid_request" error code to do it ๐Ÿ™…โ€โ™€๏ธ.

๐Ÿ’ก Note: Authorization servers and clients MAY use metadata, as defined in Sections 5 and 6, to signal the desired behavior ๐Ÿซถ

5. Authorization Server Metadata ๐ŸŽ€

The following authorization server metadata parameters [RFC8414] are introduced to signal the server's capability and policy with respect to PAR ๐Ÿ“‹.

  • pushed_authorization_request_endpoint: The URL of the pushed authorization request endpoint, where a client can post an authorization request to exchange for a "request_uri" value that's usable at the authorization server ๐Ÿ“ฎ.
  • require_pushed_authorization_requests: A boolean parameter indicating whether the authorization server accepts authorization request data only via PAR ๐Ÿ”. If omitted, the default value is "false" ๐ŸŒธ.

Note that the presence of pushed_authorization_request_endpoint is enough for a client to figure out that it may use the PAR flow โœจ. A "request_uri" value obtained from the PAR endpoint is usable at the authorization endpoint regardless of other authorization server metadata, such as "request_uri_parameter_supported" or "require_request_uri_registration" [OIDC.Disco] ๐Ÿฆ‹

6. Client Metadata ๐Ÿ’Œ

okay so the Dynamic Client Registration Protocol [RFC7591] is the API for registering OAuth 2.0 client metadata with authorization servers ๐Ÿงš. The metadata it defines, plus any registered extensions, also gives you a general data model for clients. That model is useful even when nobody is using Dynamic Client Registration, because implementations usually have some kind of UI for managing client config anyway ๐Ÿ’…. This document adds one client metadata parameter that says whether a given client has to use pushed authorization requests ๐Ÿฆ‹.

require_pushed_authorization_requests Boolean parameter that says whether PAR is the only way the client is allowed to start an authorization request. If it's omitted, the default value is "false" ๐ŸŒธ.


7. Security Considerations ๐Ÿ”ฅ

this part is serious bestie, so read it carefully ๐Ÿ˜ญ

7.1. Request URI Guessing

an attacker could try to guess a valid request URI value, replay it, and impersonate the matching client ๐Ÿ’€. The authorization server MUST account for the considerations in JAR [RFC9101], Section 10.2, clause (d) about request URI entropy ๐Ÿ”.

7.2. Open Redirection

an attacker could register a redirect URI pointing at a site they control, so they can grab authorization codes or launch other attacks on the user ๐Ÿ™ˆ. The authorization server MUST only accept new redirect URIs in the pushed authorization request from authenticated clients ๐Ÿ›ก๏ธ.

7.3. Request Object Replay

an attacker could replay a request URI they captured from a legit authorization request ๐Ÿ‘€. To cope with that, the authorization server SHOULD make request URIs one-time use โœจ.

7.4. Client Policy Change

the client policy might change between when the Request Object is lodged and when the authorization request using that Request Object shows up ๐ŸŒˆ. So it's recommended that the authorization server checks the request parameter against the client policy when it processes the authorization request ๐Ÿง.

7.5. Request URI Swapping

an attacker could capture the request URI from one request and swap it into a different authorization request ๐Ÿ˜ค. For example, in OpenID Connect, an attacker could replace a request URI asking for a high level of authentication assurance with one that only needs a lower level ๐Ÿ’”. Clients SHOULD make use of PKCE [RFC7636], a unique "state" parameter [RFC6749], or the OIDC "nonce" parameter [OIDC] in the pushed Request Object to stop this attack ๐Ÿซถ.


8. Privacy Considerations ๐ŸŒธ

OAuth 2.0 is a complex and flexible framework with privacy implications all over the place ๐Ÿฆ‹. It basically has one entity sitting in the middle of user authorization and data access between two other entities, so it's a lot ๐Ÿ’…. The privacy considerations for all of OAuth are out of scope here, because this document only defines another way to start one message sequence in the bigger framework ๐Ÿ“š. That said, PAR may improve privacy, since it reduces the chances of accidentally leaking information. It sends the authorization request data straight from the client to the authorization server over a secure connection, in the body of an HTTP request. The alternative is putting it in the query component of a URL, which goes through the user agent in plain text ๐Ÿ™ˆ๐Ÿ’–.


9. IANA Considerations ๐Ÿงš

9.1. OAuth Authorization Server Metadata

IANA registered the following values in the IANA "OAuth Authorization Server Metadata" registry of [IANA.OAuth.Parameters], which was set up by [RFC8414] ๐ŸŽ€.

Metadata Name:  "pushed_authorization_request_endpoint"
Metadata Description:  URL of the authorization server's pushed
   authorization request endpoint.
Change Controller:  IESG
Specification Document(s):  Section 5 of RFC 9126

Metadata Name:  "require_pushed_authorization_requests"
Metadata Description:  Indicates whether the authorization server
   accepts authorization requests only via PAR.
Change Controller:  IESG
Specification Document(s):  Section 5 of RFC 9126

9.2. OAuth Dynamic Client Registration Metadata

IANA registered the following value in the IANA "OAuth Dynamic Client Registration Metadata" registry of [IANA.OAuth.Parameters], which was set up by [RFC7591] ๐ŸŒˆ.

Client Metadata Name:  "require_pushed_authorization_requests"
Client Metadata Description:  Indicates whether the client is
   required to use PAR to initiate authorization requests.
Change Controller:  IESG
Specification Document(s):  Section 6 of RFC 9126

9.3. OAuth URI Registration

IANA registered the following value in the "OAuth URI" registry of [IANA.OAuth.Parameters], which was set up by [RFC6755] ๐Ÿฆ‹.

URN:  "urn:ietf:params:oauth:request_uri:"
Common Name:  A URN Sub-Namespace for OAuth Request URIs.
Change Controller:  IESG
Specification Document(s):  Section 2.2 of RFC 9126

10. References ๐Ÿ“š

10.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC6749]  Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
           RFC 6749, DOI 10.17487/RFC6749, October 2012,
           <https://www.rfc-editor.org/info/rfc6749>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8259]  Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
           Interchange Format", STD 90, RFC 8259,
           DOI 10.17487/RFC8259, December 2017,
           <https://www.rfc-editor.org/info/rfc8259>.

[RFC8414]  Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0
           Authorization Server Metadata", RFC 8414,
           DOI 10.17487/RFC8414, June 2018,
           <https://www.rfc-editor.org/info/rfc8414>.

[RFC9101]  Sakimura, N., Bradley, J., and M. Jones, "The OAuth 2.0
           Authorization Framework: JWT-Secured Authorization Request
           (JAR)", RFC 9101, DOI 10.17487/RFC9101, August 2021,
           <https://www.rfc-editor.org/info/rfc9101>.

10.2. Informative References

[IANA.OAuth.Parameters]
           IANA, "OAuth Parameters",
           <http://www.iana.org/assignments/oauth-parameters>.

[OAUTH-SECURITY-TOPICS]
           Lodderstedt, T., Bradley, J., Labunets, A., and D. Fett,
           "OAuth 2.0 Security Best Current Practice", Work in
           Progress, Internet-Draft, draft-ietf-oauth-security-
           topics-18, 13 April 2021,
           <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-
           security-topics-18>.

[OAUTH-V2] Hardt, D., Parecki, A., and T. Lodderstedt, "The OAuth 2.1
           Authorization Framework", Work in Progress, Internet-
           Draft, draft-ietf-oauth-v2-1-03, 8 September 2021,
           <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-
           v2-1-03>.

[OIDC]     Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and
           C. Mortimore, "OpenID Connect Core 1.0 incorporating
           errata set 1", November 2014,
           <http://openid.net/specs/openid-connect-core-1_0.html>.

[OIDC.Disco]
           Sakimura, N., Bradley, J., Jones, M., and E. Jay, "OpenID
           Connect Discovery 1.0 incorporating errata set 1",
           November 2014, <http://openid.net/specs/openid-connect-
           discovery-1_0.html>.

[RFC6755]  Campbell, B. and H. Tschofenig, "An IETF URN Sub-Namespace
           for OAuth", RFC 6755, DOI 10.17487/RFC6755, October 2012,
           <https://www.rfc-editor.org/info/rfc6755>.

[RFC7517]  Jones, M., "JSON Web Key (JWK)", RFC 7517,
           DOI 10.17487/RFC7517, May 2015,
           <https://www.rfc-editor.org/info/rfc7517>.

[RFC7519]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
           (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
           <https://www.rfc-editor.org/info/rfc7519>.

[RFC7523]  Jones, M., Campbell, B., and C. Mortimore, "JSON Web Token
           (JWT) Profile for OAuth 2.0 Client Authentication and
           Authorization Grants", RFC 7523, DOI 10.17487/RFC7523, May
           2015, <https://www.rfc-editor.org/info/rfc7523>.

[RFC7591]  Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and
           P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol",
           RFC 7591, DOI 10.17487/RFC7591, July 2015,
           <https://www.rfc-editor.org/info/rfc7591>.

[RFC7636]  Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key
           for Code Exchange by OAuth Public Clients", RFC 7636,
           DOI 10.17487/RFC7636, September 2015,
           <https://www.rfc-editor.org/info/rfc7636>.

[RFC8252]  Denniss, W. and J. Bradley, "OAuth 2.0 for Native Apps",
           BCP 212, RFC 8252, DOI 10.17487/RFC8252, October 2017,
           <https://www.rfc-editor.org/info/rfc8252>.

[RFC8705]  Campbell, B., Bradley, J., Sakimura, N., and T.
           Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication
           and Certificate-Bound Access Tokens", RFC 8705,
           DOI 10.17487/RFC8705, February 2020,
           <https://www.rfc-editor.org/info/rfc8705>.

[RFC8707]  Campbell, B., Bradley, J., and H. Tschofenig, "Resource
           Indicators for OAuth 2.0", RFC 8707, DOI 10.17487/RFC8707,
           February 2020, <https://www.rfc-editor.org/info/rfc8707>.

Acknowledgements ๐Ÿซถ

this spec is based on the Pushed Request Object work from the Financial-grade API Working Group at the OpenID Foundation, which you can find at https://bitbucket.org/openid/fapi/src/master/Financial_API_Pushed_Request_Object.md ๐ŸŒŸ. Huge thanks to all the WG members for their amazing contributions ๐Ÿ’œ.

We also want to thank Vladimir Dzhuvinov, Aaron Parecki, Justin Richer, Sascha Preibisch, Daniel Fett, Michael B. Jones, Annabelle Backman, Joseph Heenan, Sean Glencross, Maggie Hung, Neil Madden, Karsten Meyer zu Selhausen, Roman Danyliw, Meral Shirazipour, and Takahiko Kawasaki for their valuable feedback on this document ๐Ÿ‘‘โœจ.

Authors' Addresses ๐Ÿ’Œ

Torsten Lodderstedt
yes.com

Email: torsten@lodderstedt.net


Brian Campbell
Ping Identity

Email: bcampbell@pingidentity.com


Nat Sakimura
NAT.Consulting

Email: nat@sakimura.org


Dave Tonge
Moneyhub Financial Technology

Email: dave@tonge.org


Filip Skokan
Auth0

Email: panva.ip@gmail.com
๐Ÿ“ฆ where this page comes from