JWT

JSON Web Token の略で、署名付きの JSON でユーザー情報を安全に伝達するトークン形式

認証セキュリティ
JWT」の技術書を見る →

JWT とは

JWT (JSON Web Token) は、署名付きの JSON でユーザー情報 (クレーム) を安全に伝達するトークン形式である。サーバーサイドのセッション管理が不要で、ステートレスな認証に適する。

JWT の構造

署名型の JWT (JWS コンパクトシリアライゼーション) は、ドット (.) で区切られた 3 つのパートで構成される。Header にアルゴリズムとトークン種別、Payload にユーザー情報や有効期限などのクレーム、Signature に改ざん検知用の署名が含まれる。Header と Payload は Base64URL エンコードされているだけで暗号化はされていないため、機密情報を Payload に含めてはならない。RFC 7519 は暗号化型 (JWE コンパクトシリアライゼーション・パートが 5 つ) も JWT として定義しているが、実務で JWT と呼ばれるのはほぼこの署名型である。

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWxpY2UiLCJleHAiOjE3MDAwMDAwMDB9.signature
|-------- Header --------|.|--------- Payload ---------|.|- Signature -|

Header:  { "alg": "RS256", "typ": "JWT" }
Payload: { "sub": "123", "name": "Alice", "exp": 1700000000 }
Signature: RS256(BASE64URL(Header) + "." + BASE64URL(Payload), 秘密鍵)

JWT vs セッション

JWT とセッションの違いを以下にまとめる。

観点JWTセッション
状態管理ステートレスサーバーに保存
スケーラビリティ高い (DB 不要)セッションストアが必要
無効化困難 (有効期限まで有効)即座に無効化可能
サイズ大きい (ペイロードを含む)小さい (ID のみ)
サーバーレス相性が良い (状態を持たないため)セッションストアを別に用意することになる

サーバーレス構成では、この検証をアプリケーションの手前に寄せられる。API Gateway の HTTP API はルート単位で JWT オーソライザーを設定でき、発行者・対象者・スコープの検証を通ったリクエストだけが Lambda に届く。ただし自動で有効になるものではなくルートごとの設定が前提で、REST API に同じ機能は無い (Cognito オーソライザーか Lambda オーソライザーを使う)。

JWT のセキュリティ

トークンが漏れた場合、短い有効期限 (15 分程度) は漏洩そのものを防ぐものではなく、悪用できる時間を縮める緩和策である。無効化の困難さにはリフレッシュトークンを組み合わせ、失効させたい対象だけをサーバー側で持つ。

ペイロードの改ざんは署名で検証するが、検証の実装を誤ると署名があっても素通しになる。RFC 8725 (JWT のベストプラクティス) が挙げる典型は 2 つある。1 つはトークン自身の alg を信じて検証してしまう経路である。alg: none を受け入れれば署名なしのトークンが通り、RS256 を期待している所で alg を HS256 に書き換えられると、公開されている検証用の公開鍵をそのまま HMAC の共有鍵として使われて偽造が成立する。どちらも「受け入れるアルゴリズムと鍵はサーバー側で固定し、1 つの鍵を 1 つのアルゴリズムにしか使わない」で塞げる。もう 1 つは iss (発行者) と aud (対象者) の検証漏れで、署名は正しいが別の発行者・別の用途に向けて発行されたトークンを受け入れてしまう。ID トークンをアクセストークン代わりに通してしまう事故もこの型である。

署名アルゴリズムは、単一サービスなら共有秘密鍵の HS256、マイクロサービスなら公開鍵/秘密鍵の RS256 を使う。Cognito はユーザープールごとに RSA 鍵ペアを生成して RS256 で署名し、検証用の公開鍵を JWKS エンドポイント (https://cognito-idp.<リージョン>.amazonaws.com/<ユーザープール ID>/.well-known/jwks.json) で公開する。この署名鍵は入れ替わることがあるため、公開鍵は kid をキーにキャッシュし、未知の kid が来たら取り直す作りにする。

JWT に含めるべき情報

RFC 7519 が登録クレームとして定めているのは iss (発行者)、sub (主体・ユーザー ID)、aud (対象者)、exp (有効期限)、nbf (有効開始時刻)、iat (発行時刻)、jti (トークン識別子) の 7 つで、仕様上はいずれも使用が任意である。必須にするのは利用側のプロファイルの仕事になる。よく見かける scope (権限スコープ) はこの 7 つに含まれず、クレームとしての定義登録は RFC 8693 で行われ、OAuth 2.0 のアクセストークンを JWT で表す仕様 (RFC 9068) がその利用を規定している。

実務では、expnbf の判定に時計のずれを見込んだ許容幅を持たせる (RFC 7519 は数分を超えない範囲を目安とする)、jti を使い捨てトークンの再利用検知に使う、といった詰め方になる。独自のクレームを足すときは、他の発行者が使う名前とぶつからない名前を選ぶ。

全体像を把握するには関連書籍も有用。

この記事は役に立ちましたか?

関連用語

関連する記事