JWTは、ほぼすべての最新のWebアプリケーションで使用されています。認証ヘッダー、リフレッシュフロー、APIアクセス制御などです。また、野生(実運用)で最も一貫して誤用されている標準の一つでもあります。これらを使って構築している場合、トークンの中身、デコードと検証の違いが実際に何を意味するのか、そしてどのショートカットが静かにセキュリティを破綻させるのかを理解することは不可欠です。
JWTの構造
JWTは、ドットで区切られた3つのbase64urlエンコードされた文字列です。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoiYWxpY2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MTI3NjQ4MDAsImV4cCI6MTcxMjg1MTIwMH0.4Xr8mNkZQWpH2TvL9uY3sKdJwFqBzEcAoMnRiVePxlU
- ヘッダ — アルゴリズムとトークンタイプ(
alg,typ) - ペイロード — クレーム(アプリが実際に必要とするデータ)
- サイン — 最初の2つの部分に対するHMACまたはRSA署名
デコードすると、ペイロードは次のようになります。
{
"sub": "user_123",
"email": "alice@example.com",
"iat": 1712764800,
"exp": 1712851200
}
ここにあるものは何も暗号化されていません。トークンを保持している人なら誰でもこれらの値を読むことができます。署名は、トークンが発行された後に改ざんされていないことを証明するだけであり、内容を隠すものではありません。
デコードは検証ではない
この区別は、開発者が思っている以上に混乱する点です。
デコード トークンをドットで分割し、各セクションをbase64urlデコードします。秘密鍵は不要です。どのツールやワンライナーでも実行できます。何もインストールせずにオンラインでJWTをデコードしたい場合は、トークンを IO Tools JWT Decoder に貼り付けるだけで、ヘッダー、ペイロード、有効期限の内訳が即座にわかります。
検証 秘密鍵(または非対称アルゴリズムの場合は公開鍵)を使用して署名が有効かどうかをチェックします。また、トークンが期限切れになっていないこと、そしてクレームがアプリケーションが期待するものと一致していることも確認します。検証をスキップしてデコードされたトークンを信頼することが、認証バイパスを引き起こす原因です。
JWTを検証し、一般的なエッジケースを処理するNode.jsのコードスニペットを以下に示します。
import jwt from 'jsonwebtoken';
const SECRET = process.env.JWT_SECRET;
function verifyToken(token) {
try {
const payload = jwt.verify(token, SECRET, {
algorithms: ['HS256'], // whitelist — never allow 'none'
audience: 'myapp', // validate aud claim
});
// jwt.verify throws if exp is in the past, but be explicit:
if (payload.exp < Math.floor(Date.now() / 1000)) {
throw new Error('Token expired');
}
return payload;
} catch (err) {
// Never silently swallow verification failures
throw new Error(`Invalid token: ${err.message}`);
}
}
検証する価値のあるクレーム
JWT仕様では、サーバーが単に読み取るだけでなく、積極的にチェックすべき標準クレームを定義しています。
| クレーム | 意味 | 検証しますか? |
|---|---|---|
exp | 有効期限のタイムスタンプ | 常に — 古いトークンは実際の攻撃対象領域です |
iat | 発行時刻のタイムスタンプ | オプション。最大年齢チェックに有用です |
sub | 件名(通常はユーザーID) | はい — 期待されるユーザーと一致するか確認します |
aud | 意図されたオーディエンス | はい — サービスAのトークンがサービスBで使用されるのを防ぎます |
ほとんどのJWTライブラリは exp 自動的に検証しますが、設定した場合のみです。ライブラリのドキュメントを読んでください。デフォルトで有効だと仮定しないでください。
開発者を陥れる3つの間違い
1. の alg: none 攻撃
JWT仕様では、アルゴリズム値として noneが許可されており、これは署名がないことを意味します。一部のライブラリ、特に古いものはこれを許容し、署名検証を完全にスキップします。攻撃者は署名を剥ぎ取り、ヘッダーに "alg": "none" を設定し、任意のクレームを偽造します。サーバーはそれを信頼します。
修正:検証時にはアルゴリズムを明示的にホワイトリスト化してください。決して noneを受け入れないでください。上記のコードスニペットは、これを示すものです。 algorithms: ['HS256'].
2. 有効期限の検証をしないこと
トークンをデコードし、ペイロードをチェックせずに信頼することは、数ヶ月前に発行されたトークンがまだ受け入れられることを意味します。ユーザーのセッションが取り消された場合や、攻撃者が古いトークンを盗んだ場合、アプリケーションはそれを知ることができません。 exp 修正:有効期限はオプションではなく必須として扱ってください。特定のトークンがいつ期限切れになるかを確認するには、
IO Tools JWT Expiry Checker で クレームをデコードし、残りの時間が正確にどれくらいかを教えてくれます。これは、コードを書かずにリフレッシュフローをデバッグするのに役立ちます。 exp 3. JWTをlocalStorageに保存すること
localStorageは、ページ上の任意のJavaScriptから読み取ることができます。単一のXSS脆弱性があれば、攻撃者はユーザーの認証トークンを静かに外部に流出させることができます。ストレージオプションの比較は以下の通りです。
ストレージ
| XSSリスク | CSRFリスク | JSからアクセス可能 | localStorage | 注記 |
|---|---|---|---|---|
| 認証トークンには避けるべき | 高い | なし | はい | sessionStorage |
| localStorageと同じリスク | 高い | なし | はい | httpOnly cookie |
| 認証に最適です。SameSiteとCSRFトークンを組み合わせて使用してください | なし | 中くらい | いいえ | インメモリ(JS var) |
| はい(同じコンテキスト) | 低い | なし | リフレッシュで失われる。短命なトークンには問題ありません | httpOnlyクッキーはJavaScriptから一切読み取ることができないため、XSSによる盗難の経路が完全に排除されます。トレードオフはCSRFの露出であり、これは |
またはCSRFトークンで対処します。 SameSite=Strict JWTとセッション:正直なトレードオフ
JWTはステートレスです。サーバーはデータベースにクエリを送信することなく検証できます。これは、すべてのサービスが共有セッションストアにアクセスしたくない分散システムで役立ちます。
しかし、ステートレスには実際のコストがあります。それは、JWTが期限切れになる前に取り消せないということです。ユーザーがログアウトしたり、侵害されたりした場合、トークンは
まで有効なままです。回避策(トークンブロックリスト、短い有効期限+リフレッシュトークン)は存在しますが、複雑さを増し、多くの場合、セッションストアがすでにやっていることを再構築してしまいます。 expJWTを使用すべき場合:
複数のサービスがリクエストを独立して認証する場合、ロール/権限をトークンに直接埋め込みたい場合、またはトークンが短命で取り消し遅延が許容される場合。 セッションを使用すべき場合:
即時の取り消しが必要な場合(ログアウトが実際に機能する必要がある)、サーバーサイドレンダリングのアプリを構築している場合、またはシンプルさがステートレスなスケーラビリティを上回る場合。 数秒でトークンを検査する
今すぐJWTの中身を見たいですか?ターミナル:
またはターミナルはスキップして、トークンを
echo "YOUR.JWT.HERE" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
に貼り付けて、ヘッダーとペイロードの整形された内訳を取得します。どちらのアプローチも署名を検証するものではなく、デコードするだけです。コードを書かずに迅速に有効期限を確認するには、 IO Tools JWT Decoder JWT Expiry Checker が正確なタイムスタンプと残り時間を教えてくれます。 JWTトークン:デコード、検証、そして一般的な間違いを避ける方法 1
恵 スコアボードが到着しました!
スコアボード ゲームを追跡する楽しい方法です。すべてのデータはブラウザに保存されます。さらに多くの機能がまもなく登場します!
