コンテンツにスキップ

AI Session Notes - 2026-02-23

CORS(Cross-Origin Resource Sharing)の仕組み

学んだこと

  • CORS はブラウザだけが持つセキュリティ機能であり、サーバー間通信には適用されない
  • オリジン(Origin)は「プロトコル + ドメイン + ポート」の3つの組み合わせで、どれか1つでも異なれば別オリジン扱いになる
  • サブドメイン違い(app.example.com vs api.example.com)も別オリジンになる
  • ブラウザはリクエスト時に Origin ヘッダーを自動付与し、JavaScript からの書き換えは不可能(Forbidden Header)

詳細

なぜブラウザにだけ CORS が必要か

ブラウザはドメインごとの Cookie を自動送信する仕組みを持つ。CORS がなければ、悪意あるサイトの JS がユーザーのログイン済み Cookie を使って別サイトの API を勝手に叩けてしまう。サーバー間通信ではこの「Cookie 自動送信」が起きないため、CORS は不要。

リクエストのブロックタイミングは2パターン

  1. シンプルなリクエスト(GET など): リクエストは送信される。レスポンスも返ってくるが、ブラウザが JS への引き渡しをブロックする
  2. 複雑なリクエスト(POST + JSON など): ブラウザが事前に OPTIONS リクエスト(プリフライト)を送信し、許可されなければ本番リクエスト自体を送らない

Origin ヘッダー偽装について

curl やサーバーからは Origin を自由に設定できるが、それは自分自身の操作であり、他人の Cookie を利用できるわけではないので問題にならない。CORS が守りたいのは「ブラウザを使っている人の Cookie が第三者に悪用されること」。

同一組織内での CORS 許可

同じ会社の複数サービス間(例: app.example.comapi.example.com)では、API サーバー側が Access-Control-Allow-Origin ヘッダーで許可リストを管理し、信頼するオリジンからのアクセスを許可するのが一般的なパターン。

学んだこと

  • Cookie はブラウザのデータ保存 + サーバーへの自動送信手段
  • トークン はユーザーが認証済みであることを示す文字列。保存場所は Cookie でも localStorage でもよい
  • セッション はサーバーがユーザーごとに保持する状態(ログイン情報など)
  • この3つは入れ子の関係になることが多い: Cookie(運搬手段)の中にトークンがあり、トークンからセッション情報を得る

詳細

セッションの実現方法は2パターン

  1. サーバー側に保存: トークンはただの ID で、サーバーの DB やメモリに実データがある。トークンをキーにして引く
  2. トークン自体に情報を埋め込む: トークンに暗号化されたデータが入っており、サーバー側には保存しない(iron-session 等)

セッションの有効期限

セッション自体が切れるのではなく、トークンの保存先(Cookie)に設定された有効期限で制御される。Cookie が期限切れ → ブラウザが削除 → サーバーにトークンが届かない → 未ログイン扱い。

学んだこと

  • Cookie はリクエスト時にサーバーへ自動送信されるが、localStorage は自動送信されない(JS で明示的に送る必要がある)
  • Cookie は約 4KB、localStorage は約 5〜10MB の容量制限
  • localStorage には有効期限がなく、明示的に削除しない限り残り続ける

詳細

セキュリティ上のトレードオフ

  • httpOnly Cookie → JS から読めないため XSS で盗めないが、自動送信されるため CSRF のリスクがある
  • localStorage → 自動送信されないため CSRF は起きないが、JS から自由に読めるため XSS で盗まれる

現代のベストプラクティスは httpOnly Cookie + SameSite 属性の組み合わせで、XSS と CSRF の両方に対策する。

XSS(Cross-Site Scripting)

学んだこと

  • XSS は悪意ある JavaScript がサイト上で実行されてしまう攻撃
  • localStorage に保存した認証情報は XSS で容易に窃取される
  • httpOnly Cookie は JS からアクセスできないため、XSS による窃取を防げる

学んだこと

  • CSRF は別サイトからユーザーの Cookie を利用してリクエストを送る攻撃
  • httpOnly は「JS から読めない」だけで「送信されない」わけではないため、Cookie の自動送信を利用した CSRF は防げない
  • SameSite 属性で CSRF を防御できる

詳細

SameSite の3段階

動作
Strict 別サイトからのリクエストには一切 Cookie を付けない。安全だが、外部リンクからの遷移時にもログアウト状態になる不便さがある
Lax 別サイトからの GET(リンククリック)は許可、POST は拒否。安全性と利便性のバランスが良く、広く使われている
None 制限なし。別サイトからでも全て Cookie を付ける(Secure 属性が必須)

「Lax」は英語で「緩い、ゆるやか」の意味。Strict ほど厳格ではないが実用的な保護を提供する。

Next.js Server Actions をプロキシとして使うアーキテクチャ

学んだこと

  • 外部 API が CORS を許可していない場合、ブラウザから直接呼べないため、サーバーサイドを経由する必要がある
  • Next.js の Server Actions はこの「プロキシ」の役割を果たせる
  • この構成にすると静的ホスティング(Cloudflare Pages 等)にはデプロイできず、Node.js が動くサーバー環境が必要になる
  • ファイルシステム書き込みやシングルトンパターンを使っている場合、Edge Runtime(Cloudflare Workers 等)との互換性もない

メタ情報

  • ツール: Claude Code
  • 関連技術: CORS, HTTP, ブラウザセキュリティ, Cookie, セッション, XSS, CSRF, SameSite, Next.js, Server Actions