概要

JWT(JSON Web Token、RFC 7519)は、当事者間で安全にクレーム(主張情報)をやり取りするためのコンパクトなトークン形式です。OAuth 2.0のIDトークンや、独自APIのアクセストークンとして広く利用されます。JWTの本質は「署名によって改ざんを検知できる自己完結型のデータ構造」であり、サーバ側にセッション状態を保持しないステートレス認証を実現します。SC試験ではJWTそのものの構造理解に加え、署名アルゴリズムの選択ミスや検証不備を突く攻撃(alg:none攻撃、鍵混同攻撃)が頻出テーマです。

仕組みと動作原理

JWTの3要素構造

JWTは Header.Payload.Signature の3部分をピリオドで連結し、それぞれをBase64URLエンコードした文字列です。

要素内容
Header署名アルゴリズム(alg)とトークン種別(typ)を含むJSON{"alg":"RS256","typ":"JWT"}
Payloadクレーム(ユーザ情報・有効期限等)を含むJSON。署名されるが暗号化はされない{"sub":"1234","exp":1735689600}
SignatureHeaderとPayloadを結合した文字列に対する署名値秘密鍵/共通鍵で生成

重要:Payloadは単なるBase64URLエンコードであり暗号化ではないため、誰でもデコードして中身を読めます。機密情報(パスワード等)をPayloadに含めてはいけません。

JWTの3要素構造
Header
alg・typ(署名方式)
Payload
クレーム(署名対象・非暗号化)
Signature
改ざん検知用の署名値
Base64URLエンコード
3部分をピリオドで連結
JWT
Header.Payload.Signature

標準クレーム

クレーム意味
iss(Issuer)発行者
sub(Subject)トークンの主体(通常はユーザID)
aud(Audience)想定される受信者
exp(Expiration Time)有効期限(UNIX時間)
iat(Issued At)発行日時
jti(JWT ID)トークンの一意識別子(失効管理・リプレイ防止に利用)

署名アルゴリズムの選択:HS256 vs RS256

JWTの署名方式は大きく共通鍵方式と公開鍵方式に分かれ、システム構成によって適切な選択が異なります。

観点HS256(HMAC-SHA256、共通鍵)RS256(RSA-SHA256、公開鍵)
鍵の種類発行・検証で同一の秘密鍵を共有発行は秘密鍵、検証は公開鍵
適した構成発行者と検証者が同一・信頼できる単一システム発行者と検証者が別サービス(マイクロサービス、外部連携)
鍵の配布秘密鍵自体を検証側にも配布する必要がある(漏えいリスク)公開鍵は自由に配布可能。秘密鍵は発行者のみが保持
検証側での偽造リスク検証用の鍵で署名も可能なため、検証側が偽造できてしまう検証側は公開鍵しか持たないため偽造不可
処理コスト軽量・高速相対的に重い(非対称暗号演算)
HS256 と RS256 の比較
HS256(共通鍵) RS256(公開鍵)
鍵の種類
発行・検証で同一の秘密鍵
発行は秘密鍵・検証は公開鍵
適した構成
発行者=検証者の単一システム
発行者と検証者が分離した多サービス構成
検証側の偽造リスク
検証鍵で署名も可能=偽造できる
公開鍵のみ保持のため偽造不可
鍵配布の安全性
秘密鍵の配布自体がリスク
公開鍵は自由に配布してよい

検証フロー

受信側は署名を検証してから初めてクレームを信頼してよい、という原則が重要です。

JWT検証の流れ
1
クライアント → API
JWTをAuthorizationヘッダに付与して送信
Bearer <token>
2
API側
Headerのalgを確認し、期待するアルゴリズムか検証
algをクライアント指定のまま信用しない
3
API側
Signatureを鍵(公開鍵 or 共通鍵)で検証
改ざんされていないか確認
4
API側
exp・iss・audなどのクレームを検証
有効期限切れ・発行者不一致を拒否
5
API側
検証成功後のみPayloadの内容を信頼して処理

alg:none攻撃と鍵混同攻撃

JWTライブラリの実装不備を突く代表的な攻撃です。

攻撃手口対策
alg:none攻撃Headerのalgnoneに書き換え、署名を空にしたトークンを送信。検証側がalgをトークンの自己申告どおりに信用すると、署名検証をスキップしてしまうサーバ側で許容するアルゴリズムをホワイトリストとして固定し、トークンのalg値を信用しない
アルゴリズム混同攻撃(鍵混同攻撃)RS256運用のシステムに対し、HeaderをHS256に書き換え、本来公開されているRSA公開鍵をHMACの共通鍵として使って署名を偽造する検証時に鍵の種類とアルゴリズムの組み合わせを厳格にチェックし、公開鍵をHMAC鍵として誤用できないよう実装を分離する

トークンの有効期限設計とリフレッシュトークン

JWTはステートレスであるがゆえに、発行後の失効が原則できません(サーバ側にセッション状態がないため)。この特性を踏まえた期限設計が重要です。

トークン種別推奨有効期限保管場所の指針
アクセストークン(JWT)短命(数分〜1時間程度)メモリ上(画面遷移で消える程度)に保持し、漏えい時の被害を時間で限定
リフレッシュトークン長命(数日〜数週間)HttpOnly・Secure属性付きCookie等、JavaScriptから読み取れない領域に保管

リフレッシュトークン安全管理の要点:

  • リフレッシュトークンローテーション:使用のたびに新しいリフレッシュトークンを発行し、古いものを無効化する。同一トークンの再利用を検知したら窃取を疑いトークンチェーン全体を失効させる
  • サーバ側での失効管理:リフレッシュトークン自体はDBで状態管理し、ログアウト時やインシデント時に即座に無効化できるようにする(アクセストークンより長命なため、失効の仕組みが特に重要)
  • XSS・CSRF双方への配慮:HttpOnly CookieはXSSからは守れるがCSRF対策は別途必要(SameSite属性等)

ステートレス認証のメリット・デメリット

観点メリットデメリット
スケーラビリティサーバ側にセッションを持たないため水平スケールが容易
サービス間連携マイクロサービス間で署名検証のみで認可判断が可能
即時失効発行済みトークンを個別に無効化する標準機構がない(有効期限が来るまで有効)
トークンサイズセッションIDに比べペイロードが大きく、リクエストごとの通信量が増える
情報露出Payloadは非暗号化のため、機密情報を含めると漏えいリスクになる

SC試験での頻出ポイント

  • JWTのPayloadは暗号化されていない:署名により改ざん検知はできるが、内容の秘匿はできない点が繰り返し出題される
  • HS256とRS256の使い分け:単一システム内はHS256、発行者と検証者が異なる構成ではRS256(またはES256等の公開鍵方式)を選ぶ理由
  • alg:none攻撃の原理:検証側がalgヘッダをクライアント入力のまま信用すると署名検証を回避されること
  • アクセストークンとリフレッシュトークンの役割分担:短命トークンで被害を限定し、長命トークンは失効管理を強化するという設計思想
  • JWTの即時失効の困難さ:ステートレスゆえにログアウト即時反映が難しく、ブラックリストやリフレッシュトークンのDB管理で補う必要がある

よくある誤問・ひっかけパターン

誤り① 「JWTのPayloadは暗号化されているので機密情報を入れてもよい」→ 。PayloadはBase64URLエンコードのみで暗号化ではなく、誰でもデコードして中身を読めます。機密情報の格納は避けるべきです。

誤り② 「署名アルゴリズムはトークンのHeaderに書かれた値を使って検証すればよい」→ 。攻撃者がHeaderのalgnoneや別方式に書き換えて署名検証を回避・偽造できるため、検証側は自身が期待するアルゴリズムをサーバ側で固定し、トークンの自己申告を信用してはいけません(alg:none攻撃・鍵混同攻撃)。

誤り③ 「JWTを使えばログアウト時に即座にトークンを無効化できる」→ 。JWTはステートレスな仕組みのため発行済みトークンを個別に失効させる標準機能はなく、有効期限を短く設定する、またはサーバ側でブラックリスト・リフレッシュトークンの状態管理を別途実装する必要があります。

関連用語

重要キーワード

用語説明
JWTHeader.Payload.Signatureの3要素からなる自己完結型トークン形式(RFC 7519)
HS256HMAC-SHA256による共通鍵署名方式。発行者=検証者の構成に適する
RS256RSA-SHA256による公開鍵署名方式。発行者と検証者が分離した構成に適する
alg:none攻撃Headerのalgをnoneに書き換え署名検証を回避させる攻撃
リフレッシュトークンローテーション使用のたびに新トークンを発行し再利用を検知する安全管理手法
ステートレス認証サーバ側にセッション状態を持たず、トークン自体の検証のみで認可判断する方式