JWT は『使い方を間違えると脆弱性の宝庫』
JWT は便利だが、実装ミスでセキュリティホールが多発する技術です。本記事では編集部の視点で、正しい使い方を公開情報をもとに整理します。OAuth/OIDC 実装 もご参考に。
JWT の3要素
(1) Header:アルゴリズム・タイプ。(2) Payload:claims (sub/iat/exp 等)。(3) Signature:改竄検知。(4) 3つを . で連結。(5) Base64 URL Encoded。
署名アルゴリズムの選択
(1) HS256:HMAC-SHA256。シンプル。(2) RS256:RSA。公開鍵分離。(3) ES256:ECDSA。コンパクト。(4) EdDSA:最新標準。(5) none アルゴリズム禁止:致命的脆弱性。
必ず検証すべき claims
(1) exp (有効期限):超過時拒否。(2) iss (発行者):信頼源確認。(3) aud (対象):自サービス宛か。(4) nbf (使用開始時刻):未来トークン拒否。(5) signature:必ず検証。
失効戦略の現実
(1) JWT は本来失効困難。(2) 短期有効期限 (15分等)+リフレッシュトークン。(3) 失効リスト:Redis 等で管理。(4) セッションと併用。(5) セキュリティイベントで全失効。Redis 実践 もご参考に。
リフレッシュトークン設計
(1) 長期有効 (30日等)。(2) HttpOnly Cookieに保存。(3) 1回使用で再発行(rotation)。(4) 盗難検知:同一トークン2回使用で全失効。(5) DB に保存:失効可能に。
クライアント側保存場所
(1) HttpOnly Cookie 推奨。(2) localStorage は XSS リスク。(3) sessionStorage も同様。(4) メモリ保持:リロードで消える。(5) SameSite=Strict:CSRF 対策。Web セキュリティ実践 もご参考に。
失敗しがちなパターン
(1) none アルゴリズム受入:致命的。(2) 署名検証スキップ。(3) localStorage 保存:XSS で漏洩。(4) 長期有効 JWT:失効困難。(5) 機密情報 payload に:誰でも見える。対策は、(1)alg ホワイトリスト、(2)ライブラリ任せ+確認、(3)HttpOnly Cookie、(4)15分有効+Refresh、(5)id のみ保存、です。