フロントエンドアーキテクチャ

認証認可 ― F12前提のブラウザセキュリティアーキテクチャ ― 生成AI時代のアーキテクチャ超入門

認証認可 ― F12前提のブラウザセキュリティアーキテクチャ ― 生成AI時代のアーキテクチャ超入門

本記事について

当サイトを閲覧いただきありがとうございます。 本記事はシリーズ『生成AI時代のアーキテクチャ超入門』の「フロントエンドアーキテクチャ」カテゴリ第7弾として、フロント側の認証認可について解説する記事です。

フロントはユーザーの手元・攻撃者の手元で動きます。F12で全変数が覗かれ書き換えられる前提でブラウザ固有の防御を扱います。本記事はXSS/CSRF対策Cookie属性CSPトークン保管場所リフレッシュ戦略を解説し、認証方式(MFAPasskeyIDaaS選定)はセキュリティ章、セッション実装はソフトウェア章に委ねます。

このカテゴリの他の記事

この記事の守備範囲

記事扱う範囲
本記事(フロント認証)F12前提の認可UI / Cookie属性 / XSS / CSRF / CSP / トークン保管場所
50/01 認証設計認証強度 / MFA / Passkey / IDaaS / SSO戦略
50/02 認可とIAMRBAC / ABAC / ReBACの設計
20/07 認証・セッションサーバセッション vs JWT / OAuth実装

本記事ではMFAの要素選定」IDaaS選定」「認可モデルの詳細」は扱いません。フロント側でやるべきは、ブラウザという敵地で何を守るかです。

本記事の問いはF12で書き換えられる前提で何ができるか認証方式そのものは別章で扱います。

フロントは「究極的に信頼できない環境」

フロント側の認可判定はUIの飾りでしかありません。管理者ボタンを出す・出さないのUX制御はフロントで良いとして、本当のセキュリティチェックは必ずサーバ側で行う。この大原則を曲げた瞬間、認証設計は崩壊します。

筆者も新人時代、フロントだけで role === 'admin' を確認して「管理画面見せないから大丈夫」と思っていた設計を先輩に「F12開けば全部見えるよ」と一発で崩された経験があります。フロント認可の限界を体感するのは、この類の指摘を食らった後の方が多いです。

フロント認可はUIの出し分けだけ。本物の鍵はサーバにかけるのが鉄則です。

認証方式の4択

フロント側から見た認証方式は、実質4パターンしかありません。SPAだからJWTは2010年代の古い刷り込みで、現代の鉄板はCookie + BFFです。

方式詳細
サーバセッション(Cookie)同一ドメインなら王道・最もシンプル
JWT を localStorage 保持XSS一撃で全員分漏洩する地雷
JWT を httpOnly Cookie 保持ハイブリッド・現実的な本命
OAuth/OIDC 委譲Auth0 / Cognito / Firebase Auth など外部基盤

SPAだからJWTをlocalStorageに」は、古い情報源が未だに量産しているです。XSSが一発でも通れば、全ユーザーのトークンが持っていかれます。JWTを使うにしても「httpOnly Cookie」に入れる。生のlocalStorage運用は事故の代名詞です。

SPAJWT in localStorageは終わった設計。Cookie + BFFが現代の第一選択です。

ログインフロー(Authorization Code + PKCE)

Authorization Code + PKCE は、モダンSPAでのログインフローの鉄板です。Google・Apple・GitHub などのサードパーティ認証でも同じ形が採用されています。PKCE(Proof Key for Code Exchange、コード横取り防止の追加検証)は、公開クライアントでの「コード横取り攻撃」を潰すための追加検証です。

1. ユーザー → 認証サーバにリダイレクト(code_challenge付き)
2. ログイン後、code が返却される
3. code + PKCE verifier でトークン取得
4. BFF が検証し、Session Cookie を発行
5. 以降は Cookie でAPI通信

PKCEの発想はシンプルで、クライアントがランダムな verifier を作り、そのハッシュ(challenge)を最初のリクエストに渡します。あとでcodeをトークンに換える際、元の verifier を提示させる。途中でcodeを盗まれても、verifierを持っていない攻撃者は使えません。モバイル・SPAなど公開クライアントでは必須です。

PKCE付きAuthorization Code一択。古いImplicit Flowは絶対に使いません。

Cookie属性の設計

Cookieを使った認証では、属性の設定がそのままセキュリティを決めます。地味ですが、ここを一つ落とすだけでXSS経由でCookieが抜ける致命傷になります。

属性意味
HttpOnlyJSから読めない(XSS対策の最重要)
SecureHTTPS通信のみ送信
SameSite=Laxデフォルトの安全値・CSRF対策
SameSite=StrictCSRF完全防止(UXに影響)
Domainサブドメイン共有時に指定
Path適用するパスを絞る

現代の最低ラインはHttpOnly + Secure + SameSite=Laxの三点セットです。XSSでのCookie読み取り、HTTP経由の盗聴、クロスサイトの誤送信を、このワンセットで封じます。

属性を一つ忘れるだけで終わります。チェックリストに落として機械的に確認するのが鉄則です。

XSS と CSRF

フロントが直面する2大脅威がXSSCSRFです。別物ですが、どちらも認証システムを一撃で崩壊させます。常にセットで対策を設計する必要があります。

flowchart TB
    XSS["XSS<br/>Cross-Site Scripting<br/>悪意あるJSがページで実行"]
    CSRF["CSRF<br/>Cross-Site Request Forgery<br/>他サイトから認証済みリクエスト発火"]
    XSS_M1[CSP<br/>script-srcで許可元を絞る]
    XSS_M2[エスケープ<br/>テンプレートエンジン任せ]
    XSS_M3[HttpOnly Cookie<br/>JS から読めなくする]
    CSRF_M1[SameSite Cookie<br/>Lax/Strict]
    CSRF_M2[CSRFトークン<br/>POST要求にトークン必須]
    XSS --> XSS_M1
    XSS --> XSS_M2
    XSS --> XSS_M3
    CSRF --> CSRF_M1
    CSRF --> CSRF_M2
    XSS -.|XSSが通れば<br/>他の対策が無効化|.-> CSRF
    classDef threat fill:#fee2e2,stroke:#dc2626,stroke-width:2px;
    classDef defense fill:#dbeafe,stroke:#2563eb;
    class XSS,CSRF threat;
    class XSS_M1,XSS_M2,XSS_M3,CSRF_M1,CSRF_M2 defense;
攻撃内容対策
XSS(Cross-Site Scripting)悪意あるJSをページに混入CSP / エスケープ / HttpOnly Cookie
CSRF(Cross-Site Request Forgery)他サイトから認証済みリクエスト発火SameSite Cookie / CSRFトークン

XSSが通った瞬間、認証は事実上無効になります。攻撃者がJSを動かせる時点で、Cookie以外の情報は全部抜けるし、ユーザーに成りすましてAPIを叩けます。だからフロントのセキュリティはXSS対策が最優先、次にCSRF、という順序になります。

XSSを許した時点で負け。他の対策を積んでも前提が崩れます。

CSP(Content Security Policy)

CSP(Content Security Policy、許可するリソース出所をブラウザに宣言するHTTPヘッダ)は、ブラウザに「このページで許可するスクリプト・スタイル・画像の出所」を宣言する仕組みです。XSS対策の切り札で、インラインスクリプト禁止の設定だけでXSS攻撃の大半を無力化できます。

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://trusted.cdn.com;
  style-src 'self' 'unsafe-inline';
  object-src 'none';

インラインスクリプト禁止は <script>alert('xss')</script> のような注入を根こそぎ無効化する強力な一手ですが、既存ページに突然かけるとサイトが壊れるので段階的に入れます。Next.js や Astro は CSP用のnonceを自動付与してくれるので、モダンFW側の敷居は大きく下がりました。

CSPXSS対策の本丸。モダンFWを使っているなら導入しない理由がありません。

フロントでの認可UI

フロントでの認可は「管理者ボタンを出す/出さない」のようなUIの出し分けが中心です。これはセキュリティではなくUXの話で、画面を隠すことと、実際の権限制御は別物です。

{user.role === 'admin' && <AdminPanel />}

これで管理機能は表示されなくなりますが、攻撃者は F12 で条件を true に書き換えて AdminPanel を表示させられます。その時に管理APIが叩けないよう、API側で必ず権限チェックがいります。

設計原則は以下の通りです。

  • APIが返すデータは権限でフィルタ済みにする
  • 画面遷移ガード(router middleware)は補助的
  • そもそも見せたくない情報は取得させない

認可モデル(RBAC / ABAC / ReBAC)の設計は、フロント固有の話ではないためセキュリティ章に集約しています。本記事のフロント側で押さえるべきは「どんな認可モデルを採用しても、フロントで権限判定したら崩壊する」という大原則だけです。

フロント認可はUXの飾り。本当のセキュリティは必ずサーバ側に置きます。

トークンの保管場所

認証トークンをどこに置くかで、セキュリティレベルが段違いに変わります。現代の定石はhttpOnly Cookieを基本、メモリと併用です。

場所安全性備考
httpOnly CookieJSから読めずXSSで漏れない
Memory(Redux / 変数)リロードで消える
sessionStorageタブを閉じれば消えるがXSSには脆弱
localStorage×避ける・XSS一発で全員分漏洩

推奨構成は「短命のAccess Tokenをメモリ、長命のRefresh TokenをhttpOnly Cookie」メモリ側の漏洩はリロードで自動消失、Cookie側はhttpOnlyで防護、という二層構えが成立します。

リフレッシュトークン戦略

Access TokenRefresh Token を使い分けるのが、現代のセッション管理の標準パターンです。短命のAccess Tokenで日常のAPIを叩き、切れたら長命のRefresh Tokenで更新します。

1. Access Token(15分)期限切れ
2. クライアントが Refresh Token(30日、Cookie)を送信
3. BFF が新しい Access Token を発行
4. 必要なら Refresh Token もローテーション(再発行)

Refresh Token Rotation は、使うたびに新しいRefresh Tokenを発行し古いものを即無効化する仕組みです。もし古いトークンが再利用されたら盗まれたと検知してセッションを全失効させます。Auth0 や Firebase Auth が標準サポートしていて、これを入れると安全性が一段上がります。

Refresh Token Rotation + httpOnly Cookie が現代の推奨構成です。

ログアウトと失効

ログアウトは軽く見られがちですが、地味にセキュリティの要です。「ボタンを押したらCookieを削除」だけでは足りず、サーバ側でもRefresh Tokenを失効させる必要があります。

項目設計
ログアウトCookie削除 + サーバでRefresh Token失効
全端末ログアウト該当ユーザーのRefresh Tokenを全破棄
パスワード変更後全セッション自動失効
不審な挙動検知時管理者が強制失効可能

「全端末ログアウト」は、盗難・紛失時にユーザーが緊急停止するための機能で、重要度の高いサービスでは必須です。「ログアウトしたのに古いタブで操作できてしまう」事故は、そのままインシデントに直結します。

筆者メモ — 「見た目だけ守られている」が崩れた事例

2022年、SlackがGitHubに置いていた一部の従業員トークンが盗まれ、そのトークン経由で社内プライベートリポジトリの一部へアクセスされた事件が報じられました。仕組み自体は「トークンベースの一般的な認証」で、コード上は正しく動いていた構成です。それでも保管場所と失効運用の甘さで突破されるという教訓として、いまも語り草になっています。

同じ2022年には、Okta のサポート業務を委託していた Sitel 社の端末が侵害され、LAPSUS$ グループが Okta の内部画面にスクリーンショットを撮るレベルで到達していた、という話も流れました。SSOの大本である認証基盤が、関連会社の端末経由で揺さぶられた形です。

筆者も過去のプロジェクトで、「コードは完璧、でも運用の抜け穴で突破される」構造を目の前で見たことがあり、この手の話は他人事では済まされない、と思うようになりました。いずれも「フロント側のコードは綺麗」「プロトコルも標準」という状況で起きています。認証はコードの正しさと運用の正しさの両輪で守るもので、片方だけでは穴が残るという事実を、外から見ても分かる形で突きつけた事例でした。

認証はコードと運用の両輪。片方だけでは必ず穴が残ります。

認証設定の数値Gate・Cookie属性チェック

※ 2026年4月時点の業界相場値です。テクノロジー・人材市場の変化で陳腐化するため、定期的にアップデートが必要です。

フロント認証で「正しいデフォルト値」を曖昧にすると必ず穴が空きます。以下が現代Webの標準値です。

設定項目推奨値理由
Access Token有効期限15分漏洩時の被害最小化
Refresh Token有効期限14〜30日UXとの両立
Refresh Token Rotation有効化盗難検知で全セッション失効
Cookie HttpOnly必須XSSで読めない
Cookie Secure必須HTTPS限定
Cookie SameSiteLax(最低)or StrictCSRF対策
CSP script-src’self’ + nonceインライン禁止
Lighthouse Best Practices100点セキュリティ基礎の網羅
認証失敗レート制限5回 / 15分ブルートフォース対策
Passkey対応2026年から必須検討SMS MFA代替の標準

HttpOnly / Secure / SameSite=Laxは三点セットでCookieの最低ライン。これを一つでも欠くのは論外で、Chrome DevToolsで即座に確認できる基礎チェックです。

属性を一つ忘れるだけで終わります。チェックリストで機械的に確認します。

フロント認証の鬼門・禁じ手

フロント認証で事故る典型を整理します。どれも全ユーザー漏洩・成りすまし・セッション乗っ取りの直接原因です。

禁じ手なぜダメか
JWTをlocalStorageに保存XSS一発で全員分漏洩の地雷。2010年代の古い情報源の罠
フロントで user.role === 'admin' 分岐だけF12で true に書き換え可能。サーバ側認可が必須
OAuth Implicit Flowを新規実装2020年以降非推奨。PKCE付きAuthorization Code必須
PKCEなしでAuthorization Code公開クライアントではコード横取りで終わる
HttpOnly付け忘れXSSでCookieが読まれる。属性設定漏れは即事故
SameSite をNone + SecureなしCSRF完全素通し。SameSite=Laxがデフォルト安全
CSPに unsafe-inline を残すCSP導入の意味がない。XSS対策として機能せず
ログアウトでCookie削除のみサーバ側のRefresh Tokenが生き続ける。失効API必須
パスワードリセットで予測可能なトークンブルートフォース可能。128bitエントロピー + 15分TTL
SMS MFAだけに頼るSIMスワップ詐欺で突破。TOTP / Passkey必須
認証を自前実装穴だらけになる。Clerk / Auth.js / Auth0に委譲

2022年のOkta侵害(Lapsus$経由で366顧客影響)、2022年のLastPass流出(暗号化ボルトのコピー流出)、2023年Cloudflareへのokta経由侵入——セキュリティ専業企業すら侵入される現実。「委譲先のMFA・監査ログ・権限最小化」を運用側で監視するのが不可欠です。

認証は書くな、借りろ、見張れ。3点セットでどれも欠かしません。

AI時代の視点

AI駆動開発が前提になると、認証認可はAIに任せてはいけない領域の筆頭です。AIは認証UIをそれらしく書けますが、HttpOnly付け忘れ・SameSite誤設定・CSP未設定のような「動くけど穴だらけ」のコードを生成しがちで、人間のレビューなしでは事故を招きます。

AI時代に有利AI時代に不利
Clerk / Auth.js / NextAuth 等の外部委譲自前でCookieセッション実装
Passkey / OIDC 等の標準プロトコル独自認証トークン設計
BFF経由のhttpOnly Cookie 運用localStorageにJWT保存
CSP・HttpOnly等をコード明示デフォルト任せの設定

Next.js + ClerkNext.js + Auth.jsの組み合わせなら、AIに「ログイン機能を追加して」と言うだけで、安全な実装が数分で出てきます。逆に「自前でセッションCookieを作って」と指示すると、動くが穴だらけのコードが生成されがちです。認証は「標準ライブラリ + 外部サービスに寄せる」のが、AI時代の最も賢い判断です。

AI時代の認証はClerk / Auth.js等に委譲 + Passkey対応が安全で最速。自前実装は避けます。

よくある勘違い

  • SPAだからJWTをlocalStorageに保存するのが正しい → 2010年代の古い情報源の刷り込みです。XSS一発で全ユーザーのトークンが抜けます。httpOnly Cookie + BFFが現代の正解です
  • フロントで user.role === 'admin' を分岐すればセキュア → F12で書き換えられます。フロントはUIの出し分けだけ、本当の認可は必ずサーバAPI側で行います
  • CSPは尖ったサイトの話で自分には関係ない → Next.js や Astro は nonce 自動付与の仕組みを持っており、モダンFWを使っているなら敷居は極端に下がっています。XSS対策のベースラインです
  • ログアウトはCookieを消せば終わり → Refresh Tokenがサーバ側に生き残ります。失効APIを呼ぶまでがログアウトです

決めるべきこと — あなたのプロジェクトでの答えは?

以下の項目について、あなたのプロジェクトの答えを1〜2文で言語化してみてください。曖昧なまま着手すると、必ず後から「なぜそう決めたんだっけ」が問われます。

  • 認証方式(Cookie / JWT / 外部委譲)
  • 認証基盤(自前 / Auth0 / Cognito / Firebase Auth / Clerk)
  • Cookie属性の設定(HttpOnly / Secure / SameSite)
  • MFAの必須化(管理者のみ / 全ユーザー)
  • Passkey対応の時期
  • SSO対応SAML / OIDC
  • 認可モデルRBAC / ABAC / ReBAC
  • セッションタイムアウトとRefresh戦略

最終的な判断の仕方

フロントエンド認証の核心はフロント環境は究極的に信頼できないという前提を崩さないことです。ブラウザのJSで扱う情報は全てF12で丸見え、どんな複雑な仕組みもユーザー(=攻撃者)には書き換えられます。だからフロント認可はUIの出し分けだけ、本当のセキュリティは必ずサーバ側という大原則が揺らぎません。加えて、トークン保管場所の選定はセキュリティを直接左右します──localStorageにJWTを置く設計はXSS一撃で全ユーザー漏洩する古典的事故で、現代の正解はhttpOnly Cookie + BFF + Refresh Token Rotationです。SameSite・HttpOnly・Secure・CSPは属性ひとつ忘れるだけで致命傷になるため、機械的にチェックリスト化して漏れを潰します。

決定的な軸はAIに書かせない領域の筆頭が認証と認識することです。AIは認証UIは書けますが、HttpOnly付け忘れ・SameSite誤設定・CSP未設定・権限チェック漏れのような「見た目正しく動くが脆弱性がある」コードを頻繁に生成します。対策は Clerk / Auth.js / NextAuth / Firebase Auth / Auth0 のような外部認証基盤に委譲し、AIにはSDK呼び出しだけ書かせる。Passkey + OIDCの標準プロトコルに寄せるのも同じ理由で、標準化されたプロトコルはAIの学習データが厚く、事故率が低くなります。認可はRBACから始めて、Google Docs的な共有機能が必要になった時だけReBAC(OpenFGA / SpiceDB)へ拡張します。最初から尖った認可モデルを入れると複雑性で自滅します。

選定の優先順位

  1. 外部認証基盤に委譲(Clerk / Auth.js / Auth0 / Firebase Auth)
  2. httpOnly Cookie + BFF を基本構成に(localStorage禁止)
  3. 認可は必ずサーバ側(フロントはUI出し分けのみ)
  4. Passkey + OIDCの標準プロトコル(独自設計を避ける)

認証はAIに書かせず委譲する見た目正しく穴だらけのコードは事故の元です。

まとめ

本記事はフロント認証認可について、ブラウザ前提のXSS/CSRF対策・Cookie属性・CSP・トークン保管・Refresh Token Rotation・外部基盤委譲まで含めて解説しました。如何だったでしょうか。

F12前提で守れる範囲を見極め、httpOnly Cookie + BFFを基本に置き、認証は外部基盤に委譲する。これが2026年のフロント認証設計の現実解です。

次回はSEO(検索エンジン最適化・OGP・サイトマップ・構造化データ)について解説します。

シリーズ目次に戻る → 『生成AI時代のアーキテクチャ超入門』の歩き方

それでは次の記事も閲覧いただけると幸いです。