こんにちは。セキュリティの世界へようこそ。
日々、多くの開発者から「セキュリティってどこまでやればいいの?」という相談を受けます。教科書を読んでも眠くなるだけですよね。今日は、Web開発の現場で避けては通れない「JWT(JSON Web Token)」の、特に「時間」にまつわる守り方について、泥臭い実戦の知恵を共有します。
—
鍵を「いつまで使えるか」考えることの重要性
想像してみてください。あなたは自分の家の鍵を、信頼する友達に一時的に貸すとします。
でも、その鍵が「未来永劫ずっと使える」としたらどうでしょう? もし友達が鍵を落としたり、悪意のある誰かにコピーされたりしたら、あなたの家はいつでも泥棒に入られてしまいますよね。
Webの世界における「JWT」も同じです。JWTはサーバーが発行する「通行証」のようなものですが、これに何の制限もかけないと、一度盗まれたら「ずっと泥棒が入れる状態」になってしまいます。
そこで登場するのが、iat(Issued At:発行時刻)と nbf(Not Before:有効開始時刻)という「タイムスタンプ」の防犯装置です。
泥棒は「過去」と「未来」を狙ってくる
JWTには、攻撃者が隙を突くための2つの盲点があります。
1. 古いトークンの再利用(過去): 以前使った有効なトークンを盗んで、何度も使い回す手法。
2. フライング攻撃(未来): まだ有効ではないはずのトークンを、タイミングをずらして無理やり使おうとする手法。
これらを防ぐために、私たちはサーバー側で「この鍵はいつ作られたか?」「いつから使えるようになるか?」を厳密にチェックする必要があります。
iat (Issued At) で「鮮度」をチェックする
iat は「このトークンはいつ発行されたか」という記録です。
例えば、ユーザーがパスワードを変更した直後、古いトークンはすべて無効にしたいですよね? そういう時、「iat がパスワード変更時刻より前なら、そのトークンは門前払いする」というロジックを組むことで、不正利用を即座に遮断できます。
nbf (Not Before) で「フライング」を防ぐ
nbf は「いつから使えるか」という予約時間です。
例えば、重要なメンテナンス中に発行されたトークンを、メンテナンス終了後に一斉に有効化したい場合などに使います。これを確認することで、「まだ早すぎるぞ!」と門番が弾いてくれるわけです。
—
実装してみよう:サーバー側でのチェックロジック
では、実際にどのように検証するか、Node.js(jsonwebtoken ライブラリを想定)での例を見てみましょう。
const jwt = require('jsonwebtoken');
// サーバーに保存されている公開鍵
const publicKey = '-----BEGIN PUBLIC KEY-----...';
function verifyToken(token) {
try {
// JWTの検証プロセス
const decoded = jwt.verify(token, publicKey, {
// 許容する時間のズレ(クロックスキュー)を数秒設けるのが実務のコツ
clockTolerance: 30,
});
const now = Math.floor(Date.now() / 1000);
// 1. iatの検証:極端に古いトークンは拒否する
// 例:1時間以上前に発行されたものは古いとみなす
if (decoded.iat && (now - decoded.iat > 3600)) {
throw new Error('トークンの鮮度が古すぎます');
}
// 2. nbfの検証:まだ有効開始時間になっていない場合
if (decoded.nbf && decoded.nbf > now) {
throw new Error('まだこのトークンは使用できません');
}
console.log('認証成功!安心してお通りください。');
return decoded;
} catch (err) {
console.error('セキュリティエラー:', err.message);
// ここでエラーを投げてアクセスを拒否する
}
}
実務の現場で意識すべきこと
コード中の clockTolerance(クロックスキュー)という設定に注目してください。サーバーとクライアントの時計は、どうしても数秒ずれることがあります。厳しすぎて「正当なユーザーを弾いてしまう」のもセキュリティ事故の一つです。現場ではこの「遊び」を数秒持たせるのが大人の流儀です。
—
最後に:完璧な防犯なんて存在しない
ここまで読んで「なるほど、これだけやれば安心だ!」と思われたかもしれません。しかし、現役のホワイトハッカーとして一言だけ付け加えます。
「時間はあくまで一つの防御層に過ぎない」ということです。
iat や nbf は、泥棒が侵入するハードルを高くするための「二重ロック」です。それ以外にも、通信を暗号化する(HTTPS)、トークンを安全な場所に保存する(HttpOnly 属性のクッキーなど)、といった基本の防犯を怠ってはいけません。
セキュリティは、一度設定して終わりではありません。泥棒は常に新しい手法を探しています。今日学んだ「時間による検証」という知識を武器に、ぜひ明日からの開発に役立ててください。
一歩ずつ、強固なシステムを一緒に作っていきましょう!
コメント