セキュリティ

トークンイントロスペクションとは?RFC 7662の検証とJWT方式の使い分けを解説

アクセストークンをランダムな文字列のまま配り、リソースサーバ側でどう有効性を判定するか。この問いに標準で答えるのがトークンイントロスペクションです。RFC 7662は、保護リソースが認可サーバのエンドポイントへトークンを送り、activeを含むメタデータをJSONで受け取る手順を定めています。本記事では、照会リクエストの組み立て方、応答のどこを見て通すか弾くかを決める判定、自己完結型JWTとの使い分け、キャッシュ許容時間の決め方、認可サーバが落ちたときの縮退、そして採用を見送るべき構成までを実装の順序で整理します。

まとめ:イントロスペクションの適用条件と検証方式の結論

先に結論を置きます。トークンイントロスペクションは、不透明トークン(ランダム文字列のアクセストークン)を採る構成で、リソースサーバがトークンの有効性と権限範囲を知るための照会手段です。JWTの署名検証と二者択一の関係ではなく、失効を即座に効かせたいならイントロスペクション、1リクエストあたりの往復を増やしたくないならJWT、という選び方になります。

採用が向くのは3つ。トークンを止めた瞬間にAPIを止めたい場合、リソースサーバへ権限情報を持たせたくない場合、そして認可サーバとAPIを別組織が運用していて内部構造を共有できない場合です。逆に、同一チームが認可サーバとAPIの両方を運用し、トラフィックが秒間数千に達する構成では、往復コストが割に合いません。

実装で詰まるのはエンドポイントの呼び出しそのものではなく、その周辺にあります。照会結果をどれだけキャッシュしてよいか、認可サーバが落ちたときAPIを止めるか通すか、そして呼び出し元をどう認証するか。RFC 7662の4節はキャッシュに応答のexpが示す時刻を超えて保持してはならないという上限を置いており、この上限と失効の即時性が実務上のせめぎ合いになります。

トークンイントロスペクションの定義とリソースサーバが照会する仕組み

まず、何を誰に問い合わせる仕様なのかを、隣接する仕様と切り分けます。

RFC 7662が定める照会の対象と不透明トークンを使う前提

RFC 7662「OAuth 2.0 Token Introspection」(2015年10月発行)は、保護リソース(APIサーバ)が認可サーバへ問い合わせ、提示されたトークンのメタデータを取得するためのプロトコルを定めています。前提にあるのは、OAuth 2.0のアクセストークンがクライアントにとって不透明である、という設計です。中身を読み取れない文字列を受け取ったリソースサーバには、単体で有効性を判定する手段がありません。

そこで発行元へ聞きに行く。これがイントロスペクションの発想です。対象はアクセストークンに限りません。仕様上はリフレッシュトークンも照会でき、token_type_hintの初期値としてこの2種が登録されています。ただし実務で照会するのはほぼアクセストークンで、リフレッシュトークンの状態はトークンエンドポイントの応答から判断するほうが素直です。OAuth 2.0全体でのトークンの位置づけはOAuth 2.0の認可フローと認証・認可の違いの整理から入ると読みやすくなります。

アクセストークン検証でリソースサーバが認可サーバへ照会する流れ

処理は4段階です。クライアントがAuthorizationヘッダーでアクセストークンを送る。リソースサーバがその文字列を取り出し、認可サーバのイントロスペクションエンドポイントへPOSTする。認可サーバは自身のトークンストアを引き、activeを含むJSONを返す。リソースサーバはactiveと権限範囲を見て、APIの処理を続けるか401を返すかを決めます。

注目すべきは、この流れがAPIリクエストごとに1往復のネットワーク通信を足す点です。同一VPC内であっても数ミリ秒から数十ミリ秒が上乗せされ、認可サーバは全API呼び出しの合計と同じQPSを受けることになる。だからこそ後述のキャッシュとゲートウェイ集約が設計の中心に来ます。逆に言えば、この往復を許容できる構成でしか採用できません。

失効エンドポイントやUserInfoとの役割の違いと使い分け

名前が似た仕様が3つあるため、担当範囲を整理しておきます。混同すると、実装が二重になったり、必要な処理が抜け落ちたりします。

仕様 呼ぶ主体 返るもの 用途
イントロスペクション リソースサーバ トークンの状態と範囲 APIごとの検証
Revocation クライアント 成否のみ ログアウト時の失効
UserInfo クライアント 利用者の属性情報 プロフィール取得

RFC 7009のRevocationは状態を変える操作で、イントロスペクションは状態を読む操作です。失効させたトークンを次の照会で弾く、という形で対になります。トークンを止める側の設計はリフレッシュトークンの寿命とローテーション設計にまとめました。UserInfoはOpenID Connectの仕様で、返るのは利用者の属性であってトークンの状態ではありません。認証の可否をUserInfoの成否で代用する実装を見かけますが、これは範囲外の使い方です。

RFC 7662のリクエスト仕様とactiveを軸にした検証手順

仕様が定めるのは数個のパラメータだけです。落とし穴は、その少なさの裏にある必須要件にあります。

照会リクエストの組み立て方と呼び出し元の認証を必須にする理由

RFC 7662の2.1節が定める要求は、HTTP POSTで送り、ボディをフォーム形式(application/x-www-form-urlencoded)でエンコードし、tokenパラメータに対象の文字列を入れる、というものです。token_type_hintは任意で、認可サーバ側の検索を絞る補助にしかなりません。ヒントが外れていても、仕様は他の種別も探すことを求めています。

ここで落としてはならないのが呼び出し元の認証です。同節は、エンドポイントが何らかの認可を要求しなければならない(MUST)と規定しています。無認証で公開すると、攻撃者が手元の文字列を総当たりで投げ、有効なトークンを探し当てる走査が可能になるためです。リソースサーバをクライアントとして登録してクライアント認証を通すか、リソースサーバ専用のアクセストークンを持たせるか、いずれかを必ず入れてください。

応答のactiveと併せて検証すべき4項目および具体的な判定の順序

応答で唯一の必須項目がactiveです。ただしこれだけで通してはいけません。有効なトークンであることと、そのAPIを呼んでよいこととは別の話だからです。

項目 確認する内容 不一致のときの応答
active 有効かどうか 401を返す
scope 操作に必要な権限 403を返す
aud 自分宛てかどうか 401を返す
exp キャッシュ上限の算出 再照会する

判定は表の上から順に行います。audの確認を省く実装が多いのですが、これを飛ばすと別APIのために発行されたトークンを自分のAPIで受け入れる状態になる。マイクロサービス構成では現実的な事故要因です。ほかにclient_idsubは監査ログへ、issは認可サーバが複数ある構成での識別に使います。

active falseが返る原因の切り分けと再ログイン誘導の分岐

activeが偽で返る理由は、期限切れ、失効済み、そもそも存在しない文字列、発行元が別の認可サーバ、の4つに大別されます。仕様の2.2節は、無効なトークンに対して理由を明かさずactiveを偽にした応答を返すよう求めており、4節でも無効時に追加のクレームを含めるべきでない(SHOULD NOT)としています。つまり、認可サーバの応答から理由は読み取れません。

切り分けはクライアント側の文脈で行います。リソースサーバは一律に401を返し、レスポンスヘッダーで再認証が必要な旨だけを伝える。受け取ったクライアントは、手元にリフレッシュトークンがあれば更新を1回だけ試み、更新も失敗したらログイン画面へ誘導する、という2段階に落とします。リソースサーバ側でリトライを組んではいけません。無効な文字列を投げ直すだけの通信が増え、走査と見分けがつかなくなるためです。

JWT方式とイントロスペクション方式の使い分けを決める判断基準

ここが設計上の最大の分岐です。どちらが優れているかではなく、何を捨てるかを選びます。

自己完結型JWTと不透明トークンの検証コストと失効の効き方の差

自己完結型のJWTは、署名を検証すればリソースサーバ単体で判定が完結します。公開鍵を取得しておけば認可サーバへの通信は発生せず、レイテンシは署名検証のCPU時間だけ。代償は失効の効かなさで、取り消しても期限が来るまで検証は通り続けます。JWTの構造と署名検証の手順はJWTの仕組みと署名検証の実装で扱っています。

不透明トークンとイントロスペクションはこの逆です。照会のたびに認可サーバの現在の状態を見るため、失効は次のリクエストから効きます。権限をリソースサーバ側に持たせずに済むという副次的な利点もある。引き換えに1往復のレイテンシと、認可サーバへの依存が発生します。両者は「即時失効」と「無依存の高速検証」を交換する関係にあり、片方だけを取ることはできません。

レイテンシと可用性を軸に照会方式を選ぶ場合の実務的な判定条件

判断の入力は2つに絞れます。1つはAPIの応答時間予算のうち、認証処理に何ミリ秒を割けるか。もう1つは、認可サーバの停止をAPIの停止として受け入れられるか。この2つが決まれば方式はほぼ自動的に決まります。

  • 失効を秒単位で効かせたい、かつ照会1往復を許容できる:イントロスペクション
  • 1リクエストあたりの往復を増やせない、失効は数分の遅延を許容できる:JWTと短寿命
  • 認可サーバとAPIの運用主体が別組織で内部構造を共有できない:イントロスペクション
  • マイクロサービス間の内部通信で呼び出し回数が多い:JWTを既定にしゲートウェイで補う

実務でまず押さえるのは1番目と2番目の対比です。金融系の口座操作や権限変更のように、止めた瞬間に止まる必要がある操作はイントロスペクション。参照系が大半を占める社内APIは、寿命5分から15分のJWTで足ります。3番目と4番目は構成上の制約から導かれる選択で、迷う余地は小さくなります。

キャッシュ設計とAPIゲートウェイへ照会を集約する構成の勘所

照会1往復をそのまま毎回払う設計は、たいてい本番前に見直しになります。

照会結果のキャッシュ許容時間を決める2つの入力と上限の根拠および判断基準

キャッシュには仕様上の天井があります。RFC 7662の4節は、応答をexpが示す時刻より先までキャッシュしてはならない(MUST NOT)と規定しています。期限切れのトークンを有効として通し続ける事態を防ぐためです。実装では、キャッシュのTTLを「設定値」と「expまでの残り秒数」の小さいほうに揃えてください。

設定値そのものは、失効をどれだけ早く効かせたいかで決まります。ログアウトから最大何秒までAPIが通ってよいか、という許容値がそのままTTLの上限になる。目安を置くと、一般的な業務APIで30秒から60秒、権限変更や退会処理を含むAPIで5秒から10秒、決済のように即時性が要る操作ではキャッシュを持たせません。TTLを5分に伸ばした瞬間、退職者のトークンが5分間生き続ける構成になります。キャッシュキーはトークン文字列そのものではなく、そのハッシュ値にしてください。

APIゲートウェイで照会を集約し下流へ結果を伝える構成の条件

サービスが10本あれば、素朴に実装すると10本すべてがイントロスペクションを実装し、10本それぞれがキャッシュを持ちます。TTLも実装もばらつく。ここはゲートウェイ層で1回だけ照会し、結果を下流へ渡す構成に寄せるほうが管理しやすくなります。

渡し方には条件が付きます。subscopeを素のHTTPヘッダーで伝えると、下流サービスへ直接到達できる経路が1つでもあれば、ヘッダーを偽装した呼び出しが通ってしまう。ゲートウェイが署名付きの内部トークンを再発行して下流へ渡すか、ネットワーク的に下流への直接到達を遮断するか、どちらかを必ず満たしてください。この層で入力検査やレート制限をまとめて置く設計はAPIセキュリティの実装対策で整理しています。

認可サーバの障害時にAPI全体を止めないための縮退設計の指針

イントロスペクションを採ると、認可サーバの停止がAPI全体の停止に直結します。ここは事前に方針を決めておく箇所です。照会が失敗したとき、通す(fail-open)か止める(fail-close)か。

原則はfail-closeです。検証できないトークンを通すのは、認証を一時的に無効化するのと同じ意味になります。ただし全面停止を避ける余地はあり、TTL内の有効なキャッシュがあればそれを使う、参照系のみキャッシュの猶予を数分まで延長する、更新系はキャッシュの有無にかかわらず503を返す、という3段構えが現実的な落としどころになります。あわせて、認可サーバへの照会にはタイムアウトを短く(500ミリ秒程度)設定し、リトライは1回まで。長いタイムアウトはAPI側のスレッド枯渇を招き、障害の範囲を広げます。

イントロスペクションを採用しない条件とRFC 9701の使いどころ

最後に、採らない判断と、標準の拡張仕様を足す判断を示します。

イントロスペクションを採用すべきでない構成と代替に置く方式の選定基準

言い切ります。単一チームが認可サーバとAPIの両方を運用し、内部通信が大半を占め、失効に数分の遅延を許容できる構成では、イントロスペクションは要りません。短寿命のJWTと公開鍵による署名検証で同じ保護水準に届き、認可サーバへの依存も往復のレイテンシも発生しないためです。

また、認可サーバがマネージドサービスで、照会リクエスト数に応じた課金やレート制限がかかる場合も、既定では採らない判断になります。全APIリクエスト分の照会が課金対象になり、キャッシュ前提の設計を強いられる。この2つに当てはまるなら、JWTを既定にして、失効の即時性が要る一部のエンドポイントだけ照会を挟むハイブリッド構成へ寄せてください。全部を同じ方式で揃える必要はありません。

RFC 9701のJWT形式応答が要る場面と署名検証の実装範囲

RFC 7662の応答は素のJSONで、TLSで守られてはいるものの、応答そのものに真正性を示す仕組みがありません。ここを埋めるのがRFC 9701「JSON Web Token (JWT) Response for OAuth Token Introspection」(2025年1月発行)です。イントロスペクション応答をJWTとして署名し、必要なら暗号化して返せるようになります。

要るのは、応答が中継を経由する構成です。ゲートウェイが照会結果を下流へ渡す設計や、認可サーバとリソースサーバの運用主体が異なり、経路上の改ざんを技術的に否定したい場合。この2つ以外では、TLSと呼び出し元認証で足ります。導入する場合、リソースサーバ側にはJWTの署名検証と鍵の取得・更新の実装が増えるため、既存のJWT検証ライブラリを流用できるかを先に確認してください。

事故になる失敗パターンは照会先の無認証公開と過剰なキャッシュ

実装レビューで差し戻す構成が2つあります。1つはイントロスペクションエンドポイントを認証なしで公開する構成。RFC 7662が明確にMUSTで禁じている状態で、任意の相手がトークンの有効性を判定できてしまい、走査の踏み台になります。もう1つはキャッシュTTLを分単位まで伸ばした構成で、失効を即座に効かせるという採用理由そのものが消えます。

どちらも設計時点で防げます。エンドポイントへは必ずクライアント認証か専用トークンを課し、TTLはexpまでの残り時間と設定値の小さいほうで打ち切る。既存APIへトークン検証を組み込む設計から相談したい場合はAPI開発・システム連携で、認証・認可の方式選定から実装まで対応しています。

よくある質問

トークンイントロスペクションの設計・実装で相談の多い5点をまとめます。

トークンイントロスペクションとJWTの署名検証はどちらを使うべきですか?

失効の即時性が要るならイントロスペクション、往復のレイテンシを増やせないならJWTです。JWTは公開鍵さえあればリソースサーバ単体で検証が完結する半面、取り消したトークンも期限まで通ります。イントロスペクションは毎回認可サーバの現在の状態を見るため失効が次のリクエストから効きますが、1往復と認可サーバへの依存を負う。両方を混在させ、権限変更や決済のエンドポイントだけ照会を挟む構成も選べます。

イントロスペクションの結果はキャッシュしてもよいですか?

可能ですが上限があります。RFC 7662の4節は、応答のexpが示す時刻を超えてキャッシュしてはならないと規定しています。実装ではTTLを「設定値」と「expまでの残り秒数」の小さいほうに揃えてください。設定値は、ログアウトから最大何秒までAPIが通ってよいかで決まります。一般的な業務APIで30秒から60秒、権限変更や退会を含むAPIでは5秒から10秒が目安で、決済など即時性が要る操作では持たせません。

activeがfalseで返るのはどんなときですか?

期限切れ、失効済み、存在しない文字列、発行元が別の認可サーバ、のいずれかです。ただし仕様は無効の理由を明かさないことを求めており、応答からどれに該当するかは判別できません。リソースサーバ側は一律に401を返し、クライアント側で切り分けます。手元にリフレッシュトークンがあれば更新を1回だけ試し、それも失敗したらログイン画面へ誘導する2段階に落とすのが定石です。リソースサーバでのリトライは組みません。

イントロスペクションエンドポイントは誰が呼び出せますか?

認可された保護リソースだけです。RFC 7662の2.1節は、エンドポイントが何らかの認可を要求しなければならない(MUST)と規定しており、無認証で公開すると総当たりによるトークン走査を許します。実装方法は2つで、リソースサーバをクライアントとして登録してクライアント認証を通すか、リソースサーバ専用のアクセストークンを発行して提示させるか。あわせて4節は、呼び出せる保護リソースを個別に認可すべき(SHOULD)としています。

トークン失効(Revocation)とイントロスペクションは何が違いますか?

違いは、状態を変えるか、読むかにあります。RFC 7009のRevocationはクライアントがトークンを無効化する操作で、応答で示されるのは成否のみです。RFC 7662のイントロスペクションはリソースサーバがトークンの現在の状態を読み、有効性と権限範囲を返す操作です。2つは対で機能し、Revocationで止めたトークンが次の照会で偽として弾かれる、という流れになります。ログアウト処理には前者、APIごとの検証には後者を使います。

関連記事

資料請求

RELATED POSTS 関連記事