DevUtils
技術ガイド
セキュリティ・認証4分で読める

JWT(JSON Web Token)の構造と実務セキュリティ脆弱性防御ガイド

JWTの構造(Header, Payload, Signature)、標準クレームの正しい検証、共通鍵(HS256)と公開鍵(RS256)の違い、重大な脆弱性対策、およびCookie vs LocalStorageのトークン保管戦略を徹底解説します。

実践ツールを使ってみる

JWT デコーダー & エンコーダー

データをサーバーに送信せず、すべてブラウザ内で安全に検証・実行できます。

ツールを開く

RFC 7519標準におけるJWTの解剖図:Header, Payload, Signature

JWT(JSON Web Token)は、当事者間で安全かつコンパクトに情報をJSON形式でやり取りするためのオープン標準(RFC 7519)です。JWTはドット(.)で区切られた3つのBase64URLエンコード文字列で構成されています:

  1. Header(ヘッダー): トークンの種別("typ": "JWT")および使用されているデジタル署名・MACアルゴリズム("alg": "HS256"や"RS256")を宣言します。
  2. Payload(ペイロード/クレーム): 認証されたユーザーのID、権限スコープ、有効期限などの実データ(Claim)を格納します。
  3. Signature(署名): ヘッダーとペイロードを結合し、サーバーの秘密鍵で暗号学的ハッシュを生成した値です。これにより、ネットワーク伝送途中でトークンの内容が改ざんされていないことを検証できます。
TEXTDevUtils Code Reference
// 有効なJWTトークンの完全な構造例(DevUtilsのJWT Decoderで即座に検証可能):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

// 1. ヘッダー部分 (Base64URLデコード後):
// {"alg":"HS256","typ":"JWT"}

// 2. ペイロード部分 (Base64URLデコード後):
// {"sub":"1234567890","name":"John Doe","iat":1516239022}

// 3. 署名ハッシュ部分:
// SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

バックエンドAPIで必ず検証すべき6大標準クレーム

なりすましやリプレイ攻撃を防ぐために、サーバー側で必ず検証ルールを設けるべき標準クレームです:

  • exp (Expiration Time): トークンの有効期限切れタイムスタンプ。期限を過ぎたトークンは直ちに401 Unauthorizedで拒否しなければなりません。アクセストークンは5〜15分程度の短い有効期限を設定するのが業界標準です。
  • nbf (Not Before): トークンが有効化される日時。この時刻より前のリクエストは拒否します。
  • iat (Issued At): トークンが発行された日時。
  • iss (Issuer): トークンの発行元。信頼できる自社の認証サーバーが発行したものであるかを確認します。
  • aud (Audience): トークンの想定利用先。別サービス宛てに発行されたトークンが不正流用されるのを防ぎます。
  • sub (Subject): トークンの主題(一意のユーザーIDなど)。

共通鍵(HS256)vs 非対称鍵・公開鍵(RS256/ES256)の比較

  • HMAC-SHA256(HS256): 署名の生成と検証の両方に同一の単一シークレットキーを使用します。複数のマイクロサービスがトークンを検証する場合、全サービスで秘密鍵を共有しなければならず、どれか1つのサービスから鍵が漏洩するとシステム全体のトークンが偽造可能になる重大なリスクを抱えます。
  • RSA / ECDSA(RS256 / ES256): 公開鍵暗号方式を採用します。中央の認証サーバーのみが厳重に保管された秘密鍵(Private Key)で署名を行い、APIゲートウェイや各マイクロサービスは公開された公開鍵(Public Key / JWKS)を用いて安全に署名検証を行います。現代のクラウド分散アーキテクチャではRS256やES256の採用が強く推奨されます。

実務で多発するJWT脆弱性と堅牢な防御策

  1. alg: "none" 脆弱性: 過去の一部のライブラリにおいて、攻撃者がヘッダーに"alg": "none"を指定して署名欄を空にして送信すると、正当なトークンとして受理してしまう致命的バグがありました。本番の検証ロジックではnoneアルゴリズムを明示的に禁止してください。
  2. アルゴリズム混乱攻撃(Key Confusion Attack): RS256を想定しているサーバーに対し、攻撃者がアルゴリズムをHS256に書き換え、サーバーの公開鍵テキストを共通鍵シークレットとして署名を偽造する手口です。サーバー側で許可するアルゴリズムを厳格に固定することで防御できます。
  3. 脆弱なシークレットキー: 短く辞書に載っているような単語をHS256のキーに使用すると、オフライン総当たり攻撃ですぐに破られます。最低でも256ビット以上の十分なエントロピーを持つ暗号学的乱数を使用してください。

フロントエンドにおける安全なトークン保管:LocalStorage vs HttpOnly Cookie

  • LocalStorageへの保管: JavaScriptから容易に読み書きできる反面、万が一XSS(クロスサイトスクリプティング)脆弱性が発生した場合、悪意あるスクリプトによってトークンが即座に外部へ盗み出されます。
  • HttpOnly, Secure, SameSite Cookie: ブラウザのJavaScriptエンジンからのアクセスが完全に遮断されるため、XSSによるトークン盗難を根本から防ぎます。ただしCSRF(クロスサイトリクエストフォージェリ)攻撃を防ぐため、SameSite属性をLaxまたはStrictに設定することが必須です。
  • 実務における推奨構成: 短命なAccess TokenはJavaScriptのインメモリ(Reactの状態など)に保持し、長命なRefresh TokenはHttpOnly Cookieに格納してトークンローテーション(Rotation)を適用する二重構造が最も安全です。
タグ:JWTセキュリティ認証OAuth 2.0Webトークン
実践ツールを使ってみる

JWT デコーダー & エンコーダー

無料のオンラインJWTデコーダー。HeaderとPayloadの解析、有効期限チェック、署名検証に対応。

ツールを開く