JWTのカスタムクレームとプライベートクレーム
アプリケーション固有データのためのカスタムJWTクレームの定義・使用方法、衝突を避ける命名規則、含めるべき情報と除外すべき情報について解説します。
詳細な説明
RFC 7519で定義された登録済みクレーム(sub、exp、issなど)に加えて、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_id、plan)があります。OpenID Connectは拡張クレームにグローバルな一意性を保証するhttps:// URI形式を使用しています。
カスタムクレームに含めるべき内容:
カスタムクレームの良い候補: ユーザーロールとパーミッション、テナントまたは組織の識別子、サブスクリプションティア、フィーチャーフラグ、API動作に影響するユーザー設定。これらはリソースサーバーがすべてのリクエストで認可判断を行うために必要な値です。トークンに埋め込むことで、この情報に対するリクエストごとのデータベースクエリを回避できます。
含めるべきでない内容:
パスワード、社会保障番号、クレジットカード情報、APIキーなどの機密データを決して埋め込まないでください。JWTのペイロードはbase64urlエンコードされているだけで、暗号化されていないことを忘れないでください。トークンを傍受した誰もがペイロードをデコードできます。また、数百のエントリを持つ配列、ネストされたオブジェクト、base64エンコードされたファイルなど、大きなデータ構造も避けてください。これらはトークンサイズを膨張させ、HTTPヘッダーの制限を超える可能性があります。
クレームの同期維持:
カスタムクレームは、トークン発行時のユーザーの状態のスナップショットです。ユーザーのロールが変更されても、既存のトークンは古いロールを持ったままです。短いトークン有効期間を使用して、クレームが頻繁にリフレッシュされるようにしてください。重要な変更(パーミッション失効など)については、トークンの再発行を強制するメカニズムを実装してください。例えば、サーバーがトークンのクレームに対してチェックするバージョンカウンターをインクリメントする方法があります。
ユースケース
マルチテナントSaaSアプリケーションがJWTにtenant_idとrolesクレームを含めることで、APIエンドポイントがユーザーデータベースを照会せずにテナント分離とRBACを適用できます。