要約

  • RFC 7662は、保護リソースが認可サーバーにトークンの現在の状態を尋ね、そのリソースに関係する情報を受け取る方法を定める。
  • active: true は有効性のある結論だが、対象操作への許可でも、処理完了の証明でも、永続的な結果票でもない。
  • イントロスペクション結果のキャッシュには性能と鮮度の交換条件があり、トークン状態、リソースの判断、アプリケーションの結果を別々に記録する必要がある。

その「真」は何について真なのか

アクセストークンを受け取ったAPIが、すべての性質を手元だけで検証できるとは限らない。RFC 7662のイントロスペクションでは、保護リソースが認可サーバーへトークンを提示し、状態とメタデータを問い合わせる。応答で必須なのは真偽値の active であり、真であればスコープ、クライアント、利用者、トークン種別、有効期限、対象、発行者などが添えられることがある。

active は飾りではない。仕様上、アクティブなトークンとは一般に、その認可サーバーが発行し、失効しておらず、有効期間内にあるものを指す。認可サーバーは、期限、利用開始時刻、失効状態、署名といった該当する検査を行う。照会した保護リソースで利用できるかどうかも考慮する。したがって、この値は「通信に成功した」というだけの結果よりはるかに多くを伝える。

一方で、認可サーバーが知らない事実もある。商品が売り切れたか、送金上限を超えたか、対象レコードが別のテナントに属するか、直前の更新で版が変わったか。これらはリソース側の業務状態である。アクティブなトークンは判断材料になれるが、個別の操作を自動的に許可しない。

運用上の誤解は、二つの問いを一つに縮めたときに生まれる。「このトークンを、照会元のリソースで現在使えるか」と「この主体が、この対象に、この変更を今加えてよいか」は似ている。しかし責任を持つシステムも、必要な証拠も異なる。

標準化されたのは権限の引き渡しではない

Justin Richerは、OAuth 2.0 Token Introspectionを定めたRFC 7662の著者として記載されている。これはIETFのStandards Track文書であり、共同体の標準化成果である。Richer個人が各社の実装やポリシーを支配しているわけでも、OAuthのあらゆる仕組みを単独で発明したという意味でもない。

文書が作ったのは、二つの権限を接続するインターフェースだ。認可サーバーはトークンの発行、期限、失効、付随する許可について信頼できる情報を持つ。保護リソースは、要求されたメソッド、対象オブジェクト、現在の状態、ローカルな規則を知っている。前者から事実を受け取っても、後者の説明責任は消えない。

OAuthの基本的な役割分担でも、クライアントはアクセストークンをリソースサーバーへ提示し、リソースサーバーが検証した上で要求を扱う。イントロスペクションは検証情報を得る標準的な手段の一つである。それは「認可」という言葉を、認可サーバーだけが下す一回の万能判定に変える仕組みではない。

たとえば書き込みスコープが返っても、対象アカウントが凍結中なら更新は拒める。利用者が正しくても、追加認証が必要な操作なら条件は満たされない。監査には、トークンがアクティブだった事実と、どのリソースポリシーがどのリクエストを許可したかの両方が要る。

照会者によって見えるものが変わる

イントロスペクション応答は、誰にでも同じ全情報を見せる名簿ではない。RFC 7662は、認可サーバーが照会元の保護リソースに応じて返す情報を変えられるとしている。スコープについても、そのリソースに関係する範囲へ限定できる。情報の最小開示という点で合理的な設計である。

そのため、あるAPIのログを別のAPIへ持ち込んでも、当時の判断をそのまま再現できるとは限らない。照会元の識別、対象リソース、返された属性、時刻を一緒に扱う必要がある。RFC 8707のリソース指示子は、トークンが「どこで」使われる想定かを明示する。スコープが示す「何へのアクセス」と組み合わせても、具体的な業務命令の結果までは表さない。

応答の識別子も慎重に読むべきだ。sub、username、client_id はそれぞれ異なる主体を示しうる。aud は対象、iss は発行者、exp と nbf は時間の境界を示す。jti はトークンの識別子である。一つのトークンで多数のリクエストを行える以上、jti を注文番号や処理IDの代わりに使うことはできない。

キャッシュされた現在は、少し前の現在である

イントロスペクションを毎回行えば、認可サーバーへの依存と遅延が増える。RFC 7662は応答のキャッシュを認め、この負荷を抑える余地を残した。同時に、キャッシュは回答の即時性を下げると明記する。性能上の利得と状態の鮮度は、設定値一つで交換される。

10時にアクティブと確認した結果を5分間保存したとする。10時1分にRFC 7009の仕組みでトークンが失効しても、保護リソースは10時5分まで古い結果を使うかもしれない。認可サーバーの最新状態と、リソースサーバーの判断材料が一時的に食い違う。これは仕様が隠した穴ではなく、導入者が引き受けた時間差である。

したがってTTLは単なる高速化項目ではない。トークンの寿命、失効を反映すべき時間、操作の重大性、認可サーバー障害時の挙動を踏まえて決める。一般公開データの読み出しと、認証情報の再設定に同じTTLを当てる理由はない。

また失効は、すでに生じた効果を巻き戻さない。トークンや関連する許可を無効にして将来の利用を止めても、配送済みのデータや実行済みの送金は別の回復手続きが必要になる。資格情報の寿命と業務の寿命を混同してはいけない。

成功した検証と成功した処理の間

リソースサーバーが要求を許可した後にも、不確実性は残る。コミット前に障害が起きることも、コミット後に応答だけが失われることもある。クライアントが再試行すれば、同じアクティブなトークンを持つ二つの正当な要求が、一つの意図を二重に実行する可能性がある。

イントロスペクションのどの属性も、その問題専用の領収書ではない。重要なAPIには、アプリケーション層の永続的な操作識別子と、タイムアウト後に結果を照会できる方法が要る。冪等性キー、コマンドID、条件付き更新など、選択肢は業務によって違う。

記録すべきなのは少なくとも、トークン検証、ローカルな許可・拒否、操作ID、状態のコミット、応答の到達である。後から相関させることはできるが、一つの active に置き換えることはできない。RFC 7662の価値は、狭くても難しい問いに規格化された答えを与えたことにある。その答えの範囲を守るほど、システム全体の責任は明瞭になる。

出典