RFC 9126 OAuth 2.0 Pushed Authorization Requests
RFC 9126 - OAuth 2.0 Pushed Authorization Requests
仕様の中で PAR と略されている。
概要
RFC 6749 で定義された認可エンドポイントの仕様には以下の問題がある
- 暗号的な完全性やクライアント認証の仕組みがない
- 認可エンドポイントはユーザーエージェントからリクエストされるものであり、リクエストパラメータの機密性を守る仕組みがない
- クエリパラメータによって URL が非常に長くなる可能性がある
PAR は以下の手順によって上記の (暗号的な完全性を除いた) 問題の解決を目指す [1]。仕様の肝は認可エンドポイントのパラメータを認可サーバーにあらかじめ登録しておく点である。
最初に認可エンドポイントのリクエストパラメータを送信する際に、JAR (RFC 9101) の仕様に従って JWT を送ることもできる。こうすると認可エンドポイントへのリクエストのサイズを抑え、かつリクエストの完全性を達成しつつ、JWT の公開をせずにリクエストのサイズを減らすことができる。ただし後述するように、request
パラメータで JWT を直接指定することはできるが、request_uri
で JWT への参照を指定することはできない。
Pushed Authorization Request Endpoint
リクエスト
認可サーバーは PAR のためのエンドポイントを公開し、クライアントはここに POST リクエストを送る。パラメータは application/x-www-form-urlencoded
で送信する必要がある。以下は Section 2.1 で示されるリクエストの例である。
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
RFC 6749 では定義されない拡張パラメータを指定することも可能である。この例では PKCE (code_challenge
と code_challenge_method
) [1]に加え、クライアント認証として JWT (client_assertion_type
と client_assertion
) [2]を用いている。
認可サーバーは以下の処理を行わなければならない
- トークンエンドポイントと同様のクライアント認証[3]を行う
- リクエストパラメータに
request_uri
[4] が含まれる場合はリクエストを拒否する - 認可エンドポイントと同様のリクエストパラメータのバリデーション (
client_id
が指定されていることなど)
なお redirect_uri
の検証にあたって RFC 6749 Section 3.1.2.2 では事前に登録したものと完全一致するべきであるとされているが、PAR においては事前に登録していない値を許可しても良い[5]。
レスポンス
リクエストパラメータの検証結果が問題なかった場合、認可サーバーは短命の URI を発行し、その寿命とともにクライアントに返却する。ここで URI は urn:ietf:params:oauth:request_uri:(ランダム値)
としてもよい。レスポンスボディは JSON で、ステータスコードは 201 とする。
以下は Section 2.2 に記載のレスポンスの例である。
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
}
expires_in
は秒単位で指定される。具体的な長さは認可サーバーで決めるが、典型的には短い値 (5~600 秒)とするようだ。
エラー時には、トークンエンドポイントと同様の形式のエラーレスポンスを返却する[6]が、エラーコードとしてはトークンエンドポイントや認可エンドポイント[7]で定義されているものを用いる。ただし、認可エンドポイントのエラーコードとして定義されていないものについては、invalid_request
をデフォルトのエラーコードとして用いて良い。
これに加え、以下がエラー時のステータスコードとして定義されている:
Status Code | Description |
---|---|
405 | POST 以外のメソッドでリクエストされた場合 |
413 | リクエストボディが大きすぎる場合 |
429 | リクエストの頻度が高すぎる場合 |
以下は Section 2.3 で示されるエラーレスポンスの例である
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"
}
-
RFC 6749 Section 2.3 ↩︎
-
これは JAR でも同様に完全一致の制限は無くしても良いように思われるのだが、そのようには記載されていない ↩︎
-
RFC 6749 Section 5.2 ↩︎
-
RFC 6749 Section 4.1.2.1 ↩︎
認可エンドポイント
クライアントは Pushed Authorization Request Endpoint で受け取った request_uri
を、(ユーザーエージェントを介して) 認可エンドポイントの request_uri
パラメータを用いて認可サーバーに送信する。以下は Section 4 に記載のリクエストの例である
GET /authorize?client_id=s6BhdRkqt3&request_uri=urn%3Aietf%3Aparams
%3Aoauth%3Arequest_uri%3A6esc_11ACC5bwc014ltc14eY22c HTTP/1.1
Host: as.example.com
クライアントは Pushed Authorization Request Endpoint で受け取った request_uri
を 1 回しか用いてはならない。認可サーバーはエンドユーザーがリロード等をした場合に備えて、多重リクエストは許可しても良い。request_uri
が失効している場合にはエラーを返却しなければならない。
認可サーバーは受け取ったリクエストのバリデーションをしなければならないが、Pushed Authorization Request Endpoint ですでに行ったバリデーションは省略しても良い。ただし Pushed Authorization Request Endpoint が行われてから認可エンドポイントのリクエストまでの間に生じた認可サーバーまたはクライアントの設定の変更によってバリデーション結果が変化するような場合には、再度のバリデーションをしなければならない。