RFC 9470 OAuth 2.0 Step Up Authentication Challenge Protocol
RFC 9470 - OAuth 2.0 Step Up Authentication Challenge Protocol
リソースサーバーがアクセストークンとともにリソースへのアクセスを求められた際、そのアクセストークンが発行されるときにリソースオーナーが行った認証の強度または認証後の経過時間 (以降、これら 2 つをまとめて単に認証強度と書く) によってはリソースへのアクセスを拒否し、リソースオーナーに再度の認証を求めてクライアントにアクセストークンを取り直してもらうための方法が定義されている。
このために本仕様では以下が定められる
- アクセストークン発行時にリソースオーナーが行った認証強度が不十分な場合に、リソースサーバーが返却するべきエラーレスポンス
- 認可エンドポイントでクライアントが指定する、必要な認証強度を示す以下のパラメータ[1]
acr_values
max_age
主な処理の流れは以下のようになる
-
これらは OpenID Connect Core の Authentication Request ですでに導入されているパラメータである ↩︎
リソースサーバーが返却するエラーレスポンス
アクセストークンが不正な場合にリソースサーバーが返却するレスポンスは、すでに RFC 6750 Section 3 (Bearer トークンの場合) や RFC 9449 Section 7.1 (DPoP トークンの場合) で定義されている。
いずれの場合にも WWW-Authenticate レスポンスヘッダにおいて error
パラメータでエラーの原因を返却するが、本仕様では認証強度が不十分な場合に向けたエラーコードとして新規に insufficient_user_authentication
が定義される。
同様に WWW-Authenticate レスポンスヘッダにおいて、具体的に満たすべき認証強度を示すためのパラメータとして acr_values
と max_age
が定義される。
parameter | description |
---|---|
acr_values | リソースオーナーが満たすべき認証コンテキストリファレンスを優先度の高い順にスペース区切りで指定する。ここで指定されたもののいずれかが満たされていればよい。 |
max_age | アクセストークンを取得するためにおこなったアクティブな認証[1]から、アクセストークンが用いられた時点までの経過時間 (秒) として許容される最大値 |
以下 2 つはともに Section 3 で示されるレスポンスの例である。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="insufficient_user_authentication",
error_description="A different authentication level is required",
acr_values="myACR"
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="insufficient_user_authentication",
error_description="More recent authentication is required",
max_age="5"
-
アクティブな認証とはログインセッションがあるのでログインに成功したなどではなく、ユーザーがブラウザなどを用いて入力等を行うことによってなされた認証のことを指す認識だが、どこかにきちんと定義された言葉だったっけ? ↩︎
認可エンドポイント
リソースサーバーから insufficient_user_authentication
を受け取ったクライアントは、認可エンドポイントによってリソースオーナーに必要な強度での認証を行わせた上でアクセストークンを取得し直す必要がある。
そのために本仕様では認可エンドポイントの任意パラメータとして acr_values
と max_age
が新規に追加される。これらの仕様は OpenID Connect Core の Authentication Request で定義されているものと全く同じであるとされている。
以下はいずれも Section 4 で示されるリクエストの例である
https://as.example.net/authorize?client_id=s6BhdRkqt3
&response_type=code&scope=purchase&acr_values=myACR
https://as.example.net/authorize?client_id=s6BhdRkqt3
&response_type=code&scope=purchase&max_age=5
ここで acr_values
が指定されたが、認可サーバーが指定された認証コンテキストを満たすことができない場合は RFC 6749 Section 4.1.2 に従ってエラーを返却する。ここで用いるエラーコードは unmet_authentication_requirements
である[1]。
また、認可サーバーはアクセストークンを発行する場合に、リソースオーナーが満たした認証コンテクストと認証が行われた時刻をアクセストークンに紐づけて保存しておく必要がある[2][3]
-
これも OpenID Connect 側の OpenID Connect Core Error Code unmet_authentication_requirements という仕様を取り込んだ形と思われる ↩︎
-
そうしないとその後リソースサーバーがアクセストークン取得時のユーザーの認証強度を知ることができなくなる ↩︎
-
同様に OpenID Connect ではこれらの情報を ID トークンのそれぞれ
acr
,auth_time
クレームに含める仕様がある ↩︎
リソースサーバーがアクセストークン発行に伴い行われた認証強度を知る方法
リソースサーバーは保護されたリソースへのリクエストを受けた際に、受け取ったアクセストークンの発行のためにリソースオーナーが行った認証の強度を何らかの方法で知る必要がある。その方法については本仕様では定められないが、2 つの方法が例示されている。
[1]
アクセストークンとして JWT を用いる場合この場合はペイロードに acr
や auth_time
クレームを含めればよい。以下は Section 6.1 で示されるペイロードの例である。
{
"iss": "https://as.example.net",
"sub": "someone@example.net",
"aud": "https://rs.example.com",
"exp": 1646343000,
"iat": 1646340200,
"jti" : "e1j3V_bKic8-LAEB_lccD0G",
"client_id": "s6BhdRkqt3",
"scope": "purchase",
"auth_time": 1646340198,
"acr": "myACR"
}
[2]
トークンイントロスペクションエンドポイントを用いる場合この場合はトークンイントロスペクションエンドポイントのレスポンスとして acr
や auth_time
を含めればよい[3]。以下は Section 6.2 で示されるレスポンスの例である
HTTP/1.1 200 OK
Content-Type: application/json
{
"active": true,
"client_id": "s6BhdRkqt3",
"scope": "purchase",
"sub": "someone@example.net",
"aud": "https://rs.example.com",
"iss": "https://as.example.net",
"exp": 1639528912,
"iat": 1618354090,
"auth_time": 1646340198,
"acr": "myACR"
}