OAuth 2.0におけるJWT

OAuth 2.0でJWTがアクセストークン、IDトークン、クライアントアサーションとしてどのように使用されるか、JWT・OAuth 2.0・OpenID Connectの関係を解説します。

Usage

詳細な説明

OAuth 2.0とJWTは、現代の認証・認可システムで連携して機能する別々の仕様です。OAuth 2.0は認可フレームワーク(フロー、トークンタイプ、役割)を定義し、JWTはトークンフォーマットを定義します。両者の交差点を理解することは、安全なAPI認証の実装に不可欠です。

OAuth 2.0アクセストークンとしてのJWT:

OAuth 2.0仕様は特定のアクセストークンフォーマットを義務付けていません。トークンは不透明な文字列でも構造化されたトークンでも構いません。しかし、ほとんどの現代の実装では自己完結型であるためJWTをアクセストークンとして使用しています。リソースサーバーは認可サーバーを呼び出さずに検証できます。RFC 9068(OAuth 2.0アクセストークンのためのJSON Web Tokenプロファイル)はこのプラクティスを正式に定め、issexpaudsubclient_idjtiなどの必須クレームを定義しています。

OpenID ConnectにおけるIDトークン:

OAuth 2.0の上に構築されたOpenID Connect(OIDC)は、IDトークンがJWTでなければならないことを義務付けています。IDトークンはユーザーの認証イベントを表し、ユーザーのアイデンティティに関するクレーム(subnameemailemail_verified)を含みます。アクセストークン(API向け)とは異なり、IDトークンはクライアントアプリケーションがユーザーの身元を知るためのものです。

Authorization Code Flow:
1. ユーザーが認可サーバーにリダイレクト
2. ユーザーが認証して同意
3. サーバーがクライアントに認可コードを返す
4. クライアントがコードをトークンと交換:
   - access_token (JWT) → APIアクセス用
   - id_token (JWT) → ユーザーアイデンティティ用
   - refresh_token → 新しいトークン取得用

クライアントアサーション:

JWTは、トークン交換時にクライアント自体(ユーザーではなく)を認証するためにも使用できます。client_secretを送信する代わりに、クライアントは秘密鍵で署名したJWTを作成し、client_assertionとして送信します。これはサーバー間通信において共有秘密よりも安全であり、一部の金融API(Open Bankingなど)で必須とされています。

トークンイントロスペクション vs 自己検証:

アクセストークンが不透明な場合、リソースサーバーは認可サーバーのイントロスペクションエンドポイント(RFC 7662)を呼び出して検証する必要があります。アクセストークンがJWTの場合、リソースサーバーは署名とクレームを確認することでローカルに検証します。これによりすべてのAPIリクエストでのネットワークラウンドトリップが排除されますが、リアルタイムの失効ステータスチェック機能とのトレードオフとなります。一部のアーキテクチャでは両方を使用しています。ほとんどのリクエストにはローカルJWT検証を、長期セッションには定期的なイントロスペクションチェックを行います。

ユースケース

OAuth 2.0認可サーバーがscopeクレームを含むJWTアクセストークンを発行し、APIゲートウェイがローカルで検証することで、トークンイントロスペクション呼び出しの必要性を排除します。

試してみる — JWT Decoder

フルツールを開く