セキュリティ・認証4分で読める
JWT(JSON Web Token)の構造と実務セキュリティ脆弱性防御ガイド
JWTの構造(Header, Payload, Signature)、標準クレームの正しい検証、共通鍵(HS256)と公開鍵(RS256)の違い、重大な脆弱性対策、およびCookie vs LocalStorageのトークン保管戦略を徹底解説します。
Justin Kwak & DevUtils エンジニアリングチーム公開日: 2026-10-03
実践ツールを使ってみる
JWT デコーダー & エンコーダー
データをサーバーに送信せず、すべてブラウザ内で安全に検証・実行できます。
RFC 7519標準におけるJWTの解剖図:Header, Payload, Signature
JWT(JSON Web Token)は、当事者間で安全かつコンパクトに情報をJSON形式でやり取りするためのオープン標準(RFC 7519)です。JWTはドット(.)で区切られた3つのBase64URLエンコード文字列で構成されています:
- Header(ヘッダー): トークンの種別(
"typ": "JWT")および使用されているデジタル署名・MACアルゴリズム("alg": "HS256"や"RS256")を宣言します。 - Payload(ペイロード/クレーム): 認証されたユーザーのID、権限スコープ、有効期限などの実データ(Claim)を格納します。
- 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脆弱性と堅牢な防御策
alg: "none"脆弱性: 過去の一部のライブラリにおいて、攻撃者がヘッダーに"alg": "none"を指定して署名欄を空にして送信すると、正当なトークンとして受理してしまう致命的バグがありました。本番の検証ロジックではnoneアルゴリズムを明示的に禁止してください。- アルゴリズム混乱攻撃(Key Confusion Attack): RS256を想定しているサーバーに対し、攻撃者がアルゴリズムをHS256に書き換え、サーバーの公開鍵テキストを共通鍵シークレットとして署名を偽造する手口です。サーバー側で許可するアルゴリズムを厳格に固定することで防御できます。
- 脆弱なシークレットキー: 短く辞書に載っているような単語を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の解析、有効期限チェック、署名検証に対応。