Open4

RFC 9470 OAuth 2.0 Step Up Authentication Challenge Protocol

yapooyapoo

RFC 9470 - OAuth 2.0 Step Up Authentication Challenge Protocol

リソースサーバーがアクセストークンとともにリソースへのアクセスを求められた際、そのアクセストークンが発行されるときにリソースオーナーが行った認証の強度または認証後の経過時間 (以降、これら 2 つをまとめて単に認証強度と書く) によってはリソースへのアクセスを拒否し、リソースオーナーに再度の認証を求めてクライアントにアクセストークンを取り直してもらうための方法が定義されている。

このために本仕様では以下が定められる

  • アクセストークン発行時にリソースオーナーが行った認証強度が不十分な場合に、リソースサーバーが返却するべきエラーレスポンス
  • 認可エンドポイントでクライアントが指定する、必要な認証強度を示す以下のパラメータ[1]
    • acr_values
    • max_age

主な処理の流れは以下のようになる

脚注
  1. これらは OpenID Connect Core の Authentication Request ですでに導入されているパラメータである ↩︎

yapooyapoo

リソースサーバーが返却するエラーレスポンス

アクセストークンが不正な場合にリソースサーバーが返却するレスポンスは、すでに RFC 6750 Section 3 (Bearer トークンの場合) や RFC 9449 Section 7.1 (DPoP トークンの場合) で定義されている。

いずれの場合にも WWW-Authenticate レスポンスヘッダにおいて error パラメータでエラーの原因を返却するが、本仕様では認証強度が不十分な場合に向けたエラーコードとして新規に insufficient_user_authentication が定義される。

同様に WWW-Authenticate レスポンスヘッダにおいて、具体的に満たすべき認証強度を示すためのパラメータとして acr_valuesmax_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"
脚注
  1. アクティブな認証とはログインセッションがあるのでログインに成功したなどではなく、ユーザーがブラウザなどを用いて入力等を行うことによってなされた認証のことを指す認識だが、どこかにきちんと定義された言葉だったっけ? ↩︎

yapooyapoo

認可エンドポイント

リソースサーバーから insufficient_user_authentication を受け取ったクライアントは、認可エンドポイントによってリソースオーナーに必要な強度での認証を行わせた上でアクセストークンを取得し直す必要がある。

そのために本仕様では認可エンドポイントの任意パラメータとして acr_valuesmax_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]

脚注
  1. これも OpenID Connect 側の OpenID Connect Core Error Code unmet_authentication_requirements という仕様を取り込んだ形と思われる ↩︎

  2. そうしないとその後リソースサーバーがアクセストークン取得時のユーザーの認証強度を知ることができなくなる ↩︎

  3. 同様に OpenID Connect ではこれらの情報を ID トークンのそれぞれ acr , auth_time クレームに含める仕様がある ↩︎

yapooyapoo

リソースサーバーがアクセストークン発行に伴い行われた認証強度を知る方法

リソースサーバーは保護されたリソースへのリクエストを受けた際に、受け取ったアクセストークンの発行のためにリソースオーナーが行った認証の強度を何らかの方法で知る必要がある。その方法については本仕様では定められないが、2 つの方法が例示されている。

アクセストークンとして JWT を用いる場合[1]

この場合はペイロードに acrauth_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]

この場合はトークンイントロスペクションエンドポイントのレスポンスとして acrauth_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"
}
脚注
  1. RFC 9068 JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens ↩︎

  2. RFC 7662 OAuth 2.0 Token Introspection ↩︎

  3. これはトークンイントロスペクションエンドポイントの拡張として正式に導入されるものなのか、あくまで参考として記載されているものなのかよくわからなかった ↩︎