はじめに
RFC 8252 OAuth 2.0 for Native Apps の 7.3. Loopback Interface Redirection(ループバックインターフェースリダイレクション)の話です。
仕様
同仕様は、OAuth 2.0 のリダイレクション URI のホスト部がループバック IP アドレスの場合、認可サーバーはポート番号を可変として扱わなければならないと述べています。
The authorization server MUST allow any port to be specified at the time of the request for loopback IP redirect URIs, to accommodate clients that obtain an available ephemeral port from the operating system at the time of the request.
具体的には、認可リクエストに含まれるリダイレクション URI のホスト部が 127.0.0.1
もしくは ::1
相当の場合、その URI を事前登録されたリダイレクション URI 群と比較する際、認可サーバーは「ポート番号の差異を無視して比較する」という動作をしなければなりません。
例えば、クライアントが http://127.0.0.1/callback
をリダイレクション URI として事前登録しており、当該クライアントからの認可リクエストに redirect_uri=http://127.0.0.1:12345/callback
が含まれていた場合、認可リクエストで指定された http://127.0.0.1:12345/callback
は事前登録されているものと一致すると、認可サーバーは判断しなければなりません。
仕様衝突
問題は、RFC 8252 Section 7.3 の要求事項が、RFC 6749 The OAuth 2.0 Authorization Framework の 3.1.2.3. Dynamic Configuration の要求事項:
If the client registration included the full redirection URI, the authorization server MUST compare the two URIs using simple string comparison as defined in [RFC3986] Section 6.2.1.
および OpenID Connect Core 1.0 の 3.1.2.1. Authentication Request の要求事項:
redirect_uri
REQUIRED. Redirection URI to which the response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered at the OpenID Provider, with the matching performed as described in Section 6.2.1 of [RFC3986] (Simple String Comparison). (以下略)
と衝突することです。両要求事項とも単純文字列比較(Simple String Comparison)を明示的に要求しており、ポート番号が可変となることを許していません。
衝突解消
社内の識者(Joseph Heenan と Justin Richer)と相談した結果、歴史的経緯を踏まえ、RFC 6749 Section 3.1.2.3 と OIDC Core 1.0 Section 3.1.2.1 の要求事項よりも RFC 8252 Section 7.3 が優先する、という結論に至りました。
ただし、Financial-grade API 1.0 Baseline の 7.5. Native Apps は、RFC 8252 の元となった BCP 212 に言及した上でループバックインタフェースリダイレクションのサポートを禁止しているため、
When registering redirect URIs, authorization servers
1. shall not support "Private-Use URI Scheme Redirection"; and
2. shall not support "Loopback Interface Redirection".
FAPI の文脈では RFC 8252 Section 7.3 の動作をサポートしてはいけません。
実装
スキーム部
RFC 8252 の 7.3. Loopback Interface Redirection および 8.3. Loopback Redirect Considerations で繰り返し「ループバックリダイレクト URI は http
を使う」と述べているため、「スキーム部が http
の場合のみポート番号を可変にする」という解釈・実装もありえますが、識者に相談したところ、「http
の場合のみに限定する積極的な理由はない」とのことでした。
そのため、Authlete の実装ではスキーム部が http
でなくてもポート番号を可変として扱います。なお、RFC 8252 Section 7.3 の動作がサポートされるのは、Authlete 2.2.22 以降です。
localhost
RFC 8252 の 8.3. Loopback Redirect Considerations は、下記に引用した通り、localhost
の使用を非推奨としています。そのため、「ホスト部が localhost
の場合はポート番号を可変にしない」という実装もありえます。
While redirect URIs using
localhost
(i.e.,"http://localhost:{port}/{path}"
) function similarly to loopback IP redirects described in Section 7.3, the use oflocalhost
is NOT RECOMMENDED. Specifying a redirect URI with the loopback IP literal rather thanlocalhost
avoids inadvertently listening on network interfaces other than the loopback interface. It is also less susceptible to client-side firewalls and misconfigured host name resolution on the user's device.
しかし、(1)マイクロソフト社の Active Directory が localhost
の場合もポート番号を可変とする実装になっており(Localhost の例外)、同じ動作を要望する声が実際に存在すること、および(2)localhost
を使用するかどうかはクライアント側で完全に制御可能であること、といった理由から、Authlete の実装でも localhost
の場合もポート番号を可変として扱います。
設定
後方互換性の維持を選択できるよう、RFC 8252 Section 7.3 の動作のオン/オフを切り替えるためのフラグ『リダイレクション URI の可変性』を Authlete では用意しました。このフラグは、Service クラスの loopbackRedirectionUriVariable
プロパティー(参照:isLoopbackRedirectionUriVariable())に相当します。
おわりに
新しいユースケースや攻撃手法の登場を契機として OAuth 関連仕様は増えていきます。そのような中で、本記事で紹介した事例のように、仕様が衝突することも珍しくありません。
仕様の衝突には、「RFC 7518 で推奨とされている署名アルゴリズム RS256
がセキュリティ上の理由により Financial-grade API 1.0 Advanced では使用禁止となった」といった理解しやすいものから、RFC 9101 による破壊的仕様変更(参照:JAR (JWT-Secured Authorization Request) に関する実装者の覚書)といった難解なものまで、様々なものがあります。
仕様の変遷に追随して自社の認可サーバーの実装を更新し続ける作業はかなり労力を要します。これらの作業を専門家に任せたい方は是非 Authlete 社にお問い合わせください!