JWTのカスタムクレームとプライベートクレーム

アプリケーション固有データのためのカスタムJWTクレームの定義・使用方法、衝突を避ける命名規則、含めるべき情報と除外すべき情報について解説します。

Concept

詳細な説明

RFC 7519で定義された登録済みクレーム(subexpissなど)に加えて、JWTはアプリケーション固有の情報を持つカスタムクレームをサポートしています。これらのクレームにより、認可データ、ユーザーメタデータ、コンテキストをトークンに直接埋め込むことができ、すべてのリクエストでの追加のデータベースルックアップの必要性を削減します。

カスタムクレームの種類:

JWT仕様は3つのクレームカテゴリを定義しています。登録済みクレーム(IANAにより標準化)、パブリッククレーム(衝突耐性のある名前、通常はURI)、プライベートクレーム(当事者間で合意された名前)です。実際には、ほとんどのアプリケーションはシンプルな文字列キーのプライベートクレームを使用します。

{
  "sub": "user_abc123",
  "exp": 1700003600,
  "iss": "https://auth.example.com",
  "roles": ["admin", "editor"],
  "tenant_id": "org_xyz",
  "plan": "enterprise",
  "feature_flags": ["beta_dashboard", "new_api"]
}

命名規則:

登録済みまたはパブリッククレームとの衝突を避けるため、説明的なアプリケーション固有の名前を使用してください。一般的なアプローチには、名前空間プレフィックス(https://example.com/roles)、短いプレフィックス(x-roles)、または標準クレームと競合しない説明的な名前(tenant_idplan)があります。OpenID Connectは拡張クレームにグローバルな一意性を保証するhttps:// URI形式を使用しています。

カスタムクレームに含めるべき内容:

カスタムクレームの良い候補: ユーザーロールとパーミッション、テナントまたは組織の識別子、サブスクリプションティア、フィーチャーフラグ、API動作に影響するユーザー設定。これらはリソースサーバーがすべてのリクエストで認可判断を行うために必要な値です。トークンに埋め込むことで、この情報に対するリクエストごとのデータベースクエリを回避できます。

含めるべきでない内容:

パスワード、社会保障番号、クレジットカード情報、APIキーなどの機密データを決して埋め込まないでください。JWTのペイロードはbase64urlエンコードされているだけで、暗号化されていないことを忘れないでください。トークンを傍受した誰もがペイロードをデコードできます。また、数百のエントリを持つ配列、ネストされたオブジェクト、base64エンコードされたファイルなど、大きなデータ構造も避けてください。これらはトークンサイズを膨張させ、HTTPヘッダーの制限を超える可能性があります。

クレームの同期維持:

カスタムクレームは、トークン発行時のユーザーの状態のスナップショットです。ユーザーのロールが変更されても、既存のトークンは古いロールを持ったままです。短いトークン有効期間を使用して、クレームが頻繁にリフレッシュされるようにしてください。重要な変更(パーミッション失効など)については、トークンの再発行を強制するメカニズムを実装してください。例えば、サーバーがトークンのクレームに対してチェックするバージョンカウンターをインクリメントする方法があります。

ユースケース

マルチテナントSaaSアプリケーションがJWTにtenant_idとrolesクレームを含めることで、APIエンドポイントがユーザーデータベースを照会せずにテナント分離とRBACを適用できます。

試してみる — JWT Decoder

フルツールを開く