JWTトークンにおけるTimestamp
JWTトークンで使用されるtimestamp:exp(有効期限)、iat(発行時刻)、nbf(有効開始時刻)。バリデーション、クロックスキュー、セキュリティのベストプラクティス。
Format
exp / iat / nbf
詳細な説明
JSON Web Token(JWT)は、トークンの有効性を制御する3つの標準クレームに、秒単位のUnix timestampを使用します。これらのクレームの理解は、安全な認証・認可の実装に不可欠です。
3つのtimestampクレーム:
{
"iat": 1704067200, // Issued At: トークンの発行時刻
"nbf": 1704067200, // Not Before: この時刻より前はトークンは無効
"exp": 1704070800 // Expiration: この時刻以降はトークンは無効
}
RFC 7519で定められている通り、3つとも秒単位のUnix epochです。ここでミリ秒を使用するのはよくある間違いで、数千年先に有効期限切れとなるトークンが生成されます。
バリデーションロジック:
function validateJWT(payload) {
const now = Math.floor(Date.now() / 1000); // 現在時刻(秒)
if (payload.exp && now >= payload.exp) {
throw new Error("Token expired");
}
if (payload.nbf && now < payload.nbf) {
throw new Error("Token not yet valid");
}
// iatは情報提供用であり、通常バリデーションには使用しない
}
クロックスキューの許容:
分散システムでは、サーバーのクロックは完全には同期しません。サーバーAが発行したトークンは、サーバーBのクロックがわずかに遅れている場合、サーバーBでは未来から来たように見える可能性があります。これに対処するため、ほとんどのJWTライブラリは「クロック許容値」または「leeway」パラメータ(通常30〜60秒)を受け入れます。
// jose ライブラリの例
await jwtVerify(token, key, {
clockTolerance: 60 // 60秒のクロックスキューを許容
});
セキュリティのベストプラクティス:
- 常に
expクレームを設定してください。有効期限のないトークンは、漏洩した場合に永久に有効なままです。 - アクセストークンの有効期間は短く設定してください(5〜15分)。長いセッションにはリフレッシュトークンを使用します。
- 特定の将来の時刻にのみ有効になるべきトークン(例:事前スケジュールされたアクセス権限)には
nbfを使用してください。 - セキュリティ判断に
iatクレームを信用しないでください。これはトークン発行者の主張であり、偽造される可能性があります。
JWTのデバッグ: 認証失敗をデバッグする際は、常にトークンのexpと現在のサーバー時刻を比較してください。最も一般的な問題はトークンの期限切れであり、次に多いのが発行者と検証者の間のクロックスキューです。
ユースケース
OAuth 2.0認可サーバーは、アクセストークンに短いexp値を設定し、リソースサーバーでnbf/expを検証して、盗まれたトークンによるリプレイ攻撃を防ぐ必要があります。