JWTはモダンなWebアプリケーションの認証基盤として広く普及しています。しかし「とりあえず動いている」状態で使われることも多く、セキュリティ上の落とし穴を踏んでしまうケースも少なくありません。この記事では、JWTの内部構造から安全な実装の判断基準まで、実務で必要な知識を体系的に解説します。
JWTの3つの構成要素
JWTは `ヘッダー.ペイロード.署名` の3部構成で、それぞれBase64URLエンコードされドットで連結されます。ヘッダーには署名アルゴリズム(`alg`)とトークン種別(`typ: "JWT"`)が含まれます。ペイロードにはクレームと呼ばれる情報が入り、`sub`(サブジェクト=ユーザーID)、`exp`(有効期限のUnixタイムスタンプ)、`iat`(発行時刻)などの標準クレームと、アプリケーション固有のカスタムクレームを含めます。署名はヘッダーとペイロードを秘密鍵またはキーペアで署名したもので、トークンの改ざんを検出するために使われます。重要なのは、ペイロードはBase64URLエンコードされているだけで暗号化されておらず、誰でもデコードして中身を読めることです。機密情報はペイロードに含めてはいけません。
この手順で使うツール
JWT Decoder
JWT トークンを即デコード & 検証
HS256とRS256:署名アルゴリズムの選択
HS256(HMAC-SHA256)は共通秘密鍵を使った対称署名です。シンプルで高速ですが、署名の検証にも同じ秘密鍵が必要なため、マイクロサービスなど複数サービスでトークンを検証したい場合は秘密鍵を全サービスに配布しなければならず、鍵の漏洩リスクが上がります。RS256(RSA-SHA256)は非対称鍵を使った署名です。秘密鍵(Private Key)で署名し、公開鍵(Public Key)で検証します。公開鍵は配っても署名は作れないため、認証サーバー以外のサービスも安全に署名を検証できます。同じく公開鍵で検証する方式に、鍵と署名が短くて済む ES256(楕円曲線)もあります。マイクロサービスアーキテクチャや、外部サービスにトークン検証を委ねる場合は RS256 か ES256 が向いていて、HS256 はトークンを発行するサービスと検証するサービスが同じ、シンプルな構成で有効です。
セキュアな実装のための原則
第1に、検証するときに使うアルゴリズムをサーバー側で固定することです。トークンのヘッダーの alg をそのまま信じて検証方法を選ぶと、`alg: "none"`(署名なし)のトークンを受け入れたり、RS256 用の公開鍵を HS256 の共通鍵として使わせる「アルゴリズム混同」攻撃を受けたりします。公開鍵は公開されているので、攻撃者はそれを共通鍵にして自分で HS256 の署名を作れてしまいます。第2に、有効期限(`exp`)を必ず設定し、アクセストークンは15分〜1時間程度の短い有効期限にします。あわせて、発行者(`iss`)と宛先(`aud`)も検証し、別のサービス向けに発行されたトークンを受け入れないようにします。第3に、リフレッシュトークンを別途管理し、アクセストークンが失効したらリフレッシュトークンで再発行します。第4に、ペイロードは誰でも読めるので、パスワードや個人情報を含めないことです。第5に、保存場所です。localStorage は XSS があればスクリプトから読み出されます。HttpOnly Cookie はスクリプトから読めないぶん安全ですが、ブラウザが自動で送るため、今度は CSRF への備え(SameSite 属性やCSRFトークン)が必要になります。どちらを選んでも、XSS そのものを防ぐことが前提です。これらが守られているかは、テスト用のトークンを実際に送って確かめます。JWT Builder で exp を過去の時刻にしたトークンや、別の秘密鍵で署名したトークンを作り、サーバーが拒否するかを見てください。
この手順で使うツール
JWT Builder
Header / Payload / Secret を入力してJWTをブラウザで即生成
JWT Decoderで内容と署名を確かめる
JWT Decoder にトークンを貼り付けると、ヘッダー・ペイロードがデコードされ、有効期限があと何分か、すでに切れているかも表示されます。日本語のクレームもそのまま読めます。ここで気をつけたいのは、デコードできることと正しいトークンであることは別だという点です。ペイロードはBase64URLで書かれているだけなので、誰でも書き換えて作り直せます。正しさを確かめるには署名を検証します。HS256 などは共通鍵、RS256・ES256・PS256 などは公開鍵(PEM か JWK)を入れると、署名が合っているかがその場で分かります。alg が none のトークンや、HS256 なのに公開鍵を入れた場合(アルゴリズム混同の形)は、検証を通さずに理由を表示します。処理はブラウザの中で完結しますが、本番の秘密鍵は入れず、テスト用の鍵とトークンで確かめるのが安全です。
この手順で使うツール
JWT Decoder
JWT トークンを即デコード & 検証
まとめ
JWTは正しく実装すれば強力な認証メカニズムですが、検証するアルゴリズムの固定・有効期限と発行者・宛先の検証・保存場所に応じた XSS と CSRF への備え・機密情報のペイロード除外を守ることが安全性の前提です。既存の実装を見直す際は、JWT Decoder でトークンの中身を確認するだけでなく、署名まで検証し、期限切れや別の鍵で署名したトークンをサーバーが拒否するかを実際に試してください。