【入門編】JWTのブラックリスト管理と即時無効化の設計パターン – アプリケーションセキュリティ & 安全な開発防御ガイド

こんにちは。セキュリティの世界へようこそ。
日々、システムを守る最前線にいると、「完璧な鍵なんて存在しない」という事実に直面します。でも、だからこそ面白い。今日は、開発現場で誰もが一度は悩み、そして一度は挫折しがちな「JWTのログアウト」という難題について、一緒に紐解いていきましょう。

JWTは「魔法の通行手形」だけど……

まず、JWT(JSON Web Token)をイメージしてみてください。これは、あなたの家の鍵というよりは、「顔パスで入れるVIPチケット」に近いです。

一度そのチケットを手に入れれば、有効期限が切れるまで、誰が持っていようと門番は中に入れてしまいます。これがJWTの「ステートレス」という特徴です。サーバー側で誰が入ったかを記録しなくてもいいので、非常に高速で効率的。でも、もしそのチケットを泥棒に盗まれてしまったら?

有効期限が切れるまで、泥棒は堂々とあなたの家に居座り続けます。「ログアウトボタンを押したのに!」とあなたが叫んでも、チケット自体が有効なら、門番は「どうぞお入りください」と言ってしまうのです。

「ブラックリスト」という名の指名手配書

では、どうすればいいのでしょうか。答えはシンプル。「門番に、盗まれたチケットの指名手配リスト(ブラックリスト)を渡しておく」のです。

これが、今回解説する「Redisを使ったブラックリスト管理」の正体です。

Redisが最強の相棒である理由

なぜRedisを使うのか。それは、この指名手配リストは「爆速」で照会できなければ意味がないからです。ユーザーがリクエストを送るたびに、重いデータベースを検索していたら、システム全体が悲鳴を上げてしまいます。Redisはメモリ上で動くため、一瞬で「このチケットは無効だ!」と判断できるのです。

実装の設計パターン

では、実際にどう実装するか、泥臭い現場の知恵を少しだけ共有しますね。

1. ログアウト時の処理

ユーザーがログアウトボタンを押した瞬間、そのJWTの「JTI(JWT ID)」を取り出し、Redisに保存します。

// ログアウト処理のイメージ(Node.js / Express)
app.post(‘/logout’, async (req, res) => {
const token = req.headers.authorization.split(‘ ‘)[1];
const decoded = decodeToken(token); // トークンを解読
const jti = decoded.jti; // トークン固有のIDを取得
const exp = decoded.exp; // 有効期限を取得

// 有効期限が切れるまでの時間を計算
const ttl = exp – Math.floor(Date.now() / 1000);

if (ttl > 0) {
// Redisに指名手配リストとして保存(有効期限が来たら自動消滅するように設定)
await redisClient.set(blacklist:${jti}, ‘true’, ‘EX’, ttl);
}

res.send(‘ログアウトしました。もうそのチケットは使えません!’);
});

2. 認証ミドルウェアでのチェック

リクエストが来るたびに、そのチケットがブラックリストに載っていないかを確認します。

// 認証チェックのイメージ
async function verifyToken(req, res, next) {
const jti = getJtiFromToken(req);

// Redisにデータが存在すれば、それは「無効化されたチケット」
const isBlacklisted = await redisClient.get(blacklist:${jti});

if (isBlacklisted) {
return res.status(401).send(‘このチケットは無効です。再ログインしてください。’);
}

next(); // セーフ!
}

パフォーマンスへの影響と、賢い付き合い方

「毎回Redisに問い合わせたら遅くなるのでは?」と心配になりますよね。その直感は非常に鋭い。ですが、Redisの応答速度は1ミリ秒以下です。現代のWebアプリケーションにおいて、このコストは無視できるレベル。

ただし、「ブラックリストが巨大化しすぎてメモリを圧迫しないか?」という点は注意が必要です。そのため、上記のコード例のように、JWTの有効期限(exp)に合わせてRedisのデータも自動消滅(TTL設定)させるのが鉄則です。

まとめ:セキュリティは「バランス感覚」

今回紹介したブラックリスト方式は、完璧な「ステートレス」からは少し離れます。でも、セキュリティにおいて「利便性」と「安全性」のバランスを取ることは、最高峰のエンジニアにとっても永遠の課題です。

  • JWTは便利だけど、盗まれたら終わり。
  • ログアウト時は、指名手配リスト(Redis)にIDを登録する。
  • 期限が切れたら自動で消えるように設定する。

これだけで、あなたのシステムの堅牢性は劇的に向上します。一歩ずつ、着実に。今日からこの「指名手配リスト」の考え方を、ぜひあなたの開発の引き出しに加えてみてください。

また何か壁にぶつかったら、いつでも相談してくださいね。応援しています!

コメント

タイトルとURLをコピーしました