2026 年 5 月、「JWT を localStorage に置くな」はなぜ言われるのか、Cookie 回帰までの時系列整理(Zenn 2026-05-27) という記事がトレンド入りしました。発端は Web セキュリティの第一人者・徳丸浩氏の X 投稿で、JWT を localStorage に保存する SPA の設計が XSS に対して脆弱であるという指摘です。記事は、Authorization ヘッダ方式が一時的に主流になった経緯と、近年再び HttpOnly Cookie によるセッション方式へ「回帰」しつつある時系列を丁寧に整理しています。
弊社では受託で 「既存 Web アプリ / SPA の認証実装を点検してほしい」という相談が増えています。多くは「動いてはいるが、トークンの保存場所やリフレッシュ設計が本当に安全なのか自信がない」というものです。本記事では、こうした不安を 「Web 認証実装セキュリティ監査」という受託サービスに落とし込み、診断から是正、継続運用までの進め方を整理します。基礎的な脅威モデルは Web セキュリティ入門 を、認証基盤そのものの乗り換えは Better Auth / Supabase / Clerk への認証移行受託 を併せてご覧ください。
なぜ「トークン保存場所が分水嶺」なのか
議論の核心は 「アクセストークンをどこに置くか」です。localStorage は JavaScript から自由に読める一方、HttpOnly Cookie はスクリプトから不可視です。この一点が XSS 耐性を大きく分けます。
| 観点 | localStorage 保存 + Authorization ヘッダ | HttpOnly Cookie + 適切なフラグ |
|---|---|---|
| XSS でのトークン窃取 | JS から読めるため漏えいしやすい | HttpOnly で JS から読めず窃取困難 |
| CSRF | ヘッダ付与のため原理的に起きにくい | SameSite=Lax/Strict + CSRF トークンで対策必要 |
| サードパーティ Cookie 規制 | 影響を受けにくい | クロスサイト利用は要注意(ファーストパーティ前提) |
| クロスオリジン API 呼び出し | CORS 設定で比較的素直 | ドメイン設計・SameSite 調整が必要 |
| 実装難易度 | 一見簡単だが XSS 対策が前提条件 | サーバ側セッション / BFF が要るが堅牢 |
重要なのは 「どちらかが万能ではない」ことです。localStorage 方式でも CSP やサニタイズで XSS を封じれば運用できますが、XSS が一度でも刺さればトークンが丸ごと抜かれるという単一障害点を抱えます。一方 Cookie 方式は CSRF 対策と SameSite の設計を正しく行うことが前提です。監査では「自社の脅威モデルに対してどちらの前提条件を満たせているか」を起点に判断します。
受託案件で活きる 3 つの構造変化
構造 1: 「動けばよい」から「脅威モデル前提の認証設計」へ
かつては「ログインできれば OK」でしたが、今は XSS / CSRF / オープンリダイレクトを脅威モデルとして明示し、それぞれに対策が紐づいているかが問われます。受託では、要件定義の段階で脅威モデルを文書化し、設計判断の根拠を残すことが価値になります。脅威の洗い出し方は Web セキュリティ入門 の整理が出発点として有効です。
構造 2: フロント単体から BFF・Cookie セッション回帰へ
SPA がフロント単体でトークンを抱える構成から、BFF(Backend for Frontend)がトークンを保持し、ブラウザには HttpOnly Cookie のセッション ID だけを渡す構成への揺り戻しが進んでいます。受託では「既存 SPA を壊さずに BFF を差し込む」段階的移行の設計力が差になります。
構造 3: 単発診断から継続的なセキュリティ運用へ
依存ライブラリの脆弱性やサードパーティスクリプトは日々変化します。一度診断して終わりではなく、継続的に再監査する運用へのニーズが高まっています。評価の枠組みは SCS(セキュリティ評価)ガイド の考え方を採り入れ、定点観測できる形に落とします。
受託で提供する「Web 認証実装セキュリティ監査」5 フェーズ
フェーズ 1: 現状診断
- トークン保存箇所の棚卸し(
localStorage/sessionStorage/ Cookie / メモリ) - 認証フロー図化(ログイン・リフレッシュ・ログアウト・失効)
- 使用ライブラリ・バージョン・既知脆弱性の確認
フェーズ 2: 脅威評価
- XSS / CSRF / オープンリダイレクト / トークン固定化の点検
- CSP・
SameSite・HttpOnly・Secureフラグの現状確認 - リフレッシュトークンの有効期限・ローテーション・失効方式の評価
フェーズ 3: 是正設計
- トークン保存方式の方針決定(Cookie セッション / BFF 導入の要否)
- CSP 設計(
nonce/strict-dynamicの採否) - リフレッシュトークンローテーションと失効リスト設計
フェーズ 4: 是正実装・PR レビュー
- 是正コードの実装または既存 PR のレビュー
SameSite/HttpOnly/Secure設定の反映確認- 自動テスト(認証フロー・失効・CSRF)の追加
フェーズ 5: 再監査・運用(継続)
- 是正後の再診断と差分確認
- 依存ライブラリ・CSP 違反レポートの定点観測
- インシデント時の失効・ローテーション手順の整備
受託向け技術スタック標準セット
| レイヤ | 推奨 | 代替 |
|---|---|---|
| 認証方式 | サーバセッション + BFF | OIDC / OAuth 2.1(外部 IdP) |
| トークン保存 | HttpOnly + Secure + SameSite Cookie | メモリ保持(短命アクセストークン) |
| CSP / ヘッダ | CSP(nonce ベース)+ HSTS + X-Content-Type-Options | report-only から段階導入 |
| CSRF 対策 | SameSite + Double Submit / Synchronizer Token | Origin / Referer 検証併用 |
| 監査・検査ツール | 依存脆弱性スキャン + DAST + CSP レポート収集 | 手動コードレビュー併用 |
ツールはあくまで補助で、「脅威モデルに沿った設計判断」が主役である点は変わりません。
どの案件に必要か / 不要か
| 監査が必要なケース | 監査が過剰なケース |
|---|---|
SPA で localStorage にトークンを置いている | 静的サイトで認証機能がない |
| 個人情報・決済情報を扱う | 社内クローズドな検証用ツール |
| リフレッシュトークンの設計が曖昧 | フルマネージド IdP に全面委譲済みで自前実装が皆無 |
| サードパーティスクリプトを多数読み込む | 公開済みの読み取り専用コンテンツのみ |
受託契約に書く 6 つの条項
| 条項 | 内容 | 顧客が確認すべきこと |
|---|---|---|
| 診断範囲 | 対象アプリ・ドメイン・除外範囲の明記 | サブドメインや外部 API が範囲内か |
| 検査方法 | 静的・動的・手動の手法と非破壊の取り決め | 本番環境での実施可否 |
| 是正責任の分界 | 報告のみか実装まで含むか | 自社改修分との線引き |
| 再現データの扱い | 取得した認証情報・PoC の保管と破棄 | 機密保持と保存期間 |
| 重大脆弱性の通知 | 緊急度に応じた即時報告フロー | 連絡経路と SLA |
| 再監査の条件 | 是正後の再診断の範囲と回数 | 追加費用の有無 |
価格モデル — Web 認証セキュリティ監査パッケージ
| プラン | 形態 | 価格レンジ(税別) | 対象 |
|---|---|---|---|
| スポット診断 | 一括 | 80 万円〜 | 単一アプリの認証実装を一度点検 |
| Lite | 月額 | 8 万円〜 | 小規模・定点観測のみ |
| Standard | 月額 | 20 万円〜 | 継続監査 + 月次レポート |
| Enterprise | 月額 | 50 万円〜 | 複数アプリ・BFF 運用・SLA 付き |
| 是正実装 | 一括 | 60 万円〜 | 診断後の是正コード実装 |
金額は規模・対象数・本番環境の制約により変動するため、最終的には個別見積りとなります。
顧客側 ROI 試算
| 効果 | 試算の考え方 |
|---|---|
| 情報漏えいインシデント回避 | 漏えい時の対応・通知・賠償コストの回避 |
| 是正の手戻り削減 | リリース前是正により本番改修コストを圧縮 |
| 脆弱性診断対応工数 | 診断指摘の都度対応を月次運用で平準化 |
| 取引先の信頼維持 | BtoB の継続取引・与信維持に寄与 |
仮にスポット診断 + 是正実装で初期 140 万円程度を投じても、一度の重大インシデント対応コスト(調査・通知・補償・信頼失墜)に比べれば桁が小さいことが多く、対象が個人情報や決済を扱うアプリであれば、回避できる損失額の期待値で十分に回収できる水準に収まります。
ハマりやすい 5 つの落とし穴
落とし穴 1: localStorage から Cookie に移すだけで満足する
保存場所を変えても、SameSite や CSRF 対策が伴わなければ別のリスクに付け替わるだけです。移行は対策セットで行います。
落とし穴 2: CSP を未設定のまま放置する
XSS の最後の防壁である CSP がないと、localStorage だろうと Cookie だろうとスクリプト注入の被害が広がります。report-only から段階導入するのが現実的です。
落とし穴 3: リフレッシュトークンを実質無期限にする
長命なリフレッシュトークンは窃取時の被害が甚大です。ローテーションと失効リストを設計に含めます。
落とし穴 4: SPA 前提のまま BFF を導入しない
フロントにトークンを持たせ続ける限り XSS の射程に入ります。機微情報を扱うなら BFF でトークンを隠す選択を検討します。
落とし穴 5: サードパーティスクリプトを放置する
広告・解析・チャットなどの外部スクリプトは XSS の侵入口になり得ます。読み込み元の棚卸しと CSP での許可制御が必要です。
90 日アクションプラン
| 週 | 取り組み |
|---|---|
| 第 1〜2 週 | トークン保存箇所の棚卸し・認証フロー図化 |
| 第 3〜4 週 | XSS / CSRF / オープンリダイレクトの脅威評価 |
| 第 5〜6 週 | CSP・SameSite・HttpOnly の現状確認と是正方針決定 |
| 第 7〜9 週 | 是正実装・PR レビュー・テスト追加 |
| 第 10〜11 週 | BFF / Cookie セッション移行の段階適用 |
| 第 12〜13 週 | 再監査・定点観測の運用化・引き継ぎ |
まとめ
「JWT を localStorage に置くな」という議論は、「保存場所を変えれば解決」という単純な話ではなく、脅威モデルに沿って認証設計全体を見直すべきという問いかけです。HttpOnly / Secure / SameSite / CSP / リフレッシュトークン設計 / BFF を一体で捉えれば、localStorage と Cookie のどちらを選ぶにせよ、前提条件を満たしているかが判断軸になります。弊社の Web 認証実装セキュリティ監査は、この判断を診断・是正・継続運用まで伴走してかたちにします。既存アプリの認証に少しでも不安があれば、お問い合わせフォーム からお気軽にご相談ください。
Sources
- 「JWT を localStorage に置くな」はなぜ言われるのか、Cookie 回帰までの時系列整理(Zenn 2026-05-27)
- OWASP の認証・セッション管理に関する一般的ベストプラクティス(Cheat Sheet 等)
- Web セキュリティ入門
- SCS(セキュリティ評価)ガイド
- Better Auth / Supabase / Clerk への認証移行受託