RFC 9126
OAuth 2.0 Pushed Authorization Requests
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 Notice ๐
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 ๐ง
- Authenticate the client the same way it does at the token endpoint (Section 2.3 of [RFC6749]).
- Reject the request if the "request_uri" authorization request parameter is provided ๐ซ
- 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 ๐ง :
- If applicable, decrypt the Request Object as specified in JAR [RFC9101], Section 6.1. ๐
- Validate the Request Object signature as specified in JAR [RFC9101], Section 6.2. โ
- 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
- ietf: rfc9126 2021-09
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms