Cookie と認証

Cookie の属性、Bearer Token、セッション、OAuth、Passkeys。Web 認証の基礎セットを一通り。

Cookie の基本

サーバが Set-Cookie ヘッダーで送り、ブラウザが保存。同じドメインへのリクエストで自動送信。

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600

Cookie 属性

属性意味
HttpOnlyJS から読めない(XSS 緩和)
SecureHTTPS のみ送信
SameSite=Strictクロスサイト送信なし
SameSite=Laxトップレベルナビのみ送信(既定)
SameSite=None常に送信。Secure 必須
Path=/送信対象パス
Domain=.example.comサブドメイン共有
Max-Age=3600秒単位の有効期間
Expires=...絶対日時
Partitioned3rd-party 用の分離(CHIPS)
__Host- プリフィックス追加保証(Secure, Path=/, Domain なし)
__Secure- プリフィックスSecure 必須

SameSite

2026 春現在、3rd-party Cookieはブラウザによって制限が進んでいる(Safari ITP、Firefox ETP、Chrome の Privacy Sandbox)。

JS から Cookie を扱う

// HttpOnly でないものだけ
document.cookie = "name=value; path=/; max-age=3600"

// 取得(パース必要)
const cookies = Object.fromEntries(
  document.cookie.split("; ").map((c) => c.split("="))
)

// 削除(過去の Expires)
document.cookie = "name=; expires=Thu, 01 Jan 1970 00:00:00 GMT"

新しい Cookie Store API(一部ブラウザ)

await cookieStore.set({ name: "x", value: "1", path: "/", sameSite: "lax" })
const c = await cookieStore.get("x")
await cookieStore.delete("x")

Cookie ベース vs Token ベース

CookieBearer Token
送信自動明示的に Authorization ヘッダー
JS アクセスHttpOnly で不可localStorage 等にあれば XSS で取られる
CSRFSameSite + トークンで対策原則無関係
クロスドメインSameSite=None + CORS credentialsCORS の Authorization 許可
モバイルアプリ使えるが煩雑素直
用途SSR / 同一オリジン WebSPA / API / モバイル

Bearer Token(JWT 等)

await fetch("/api/me", {
  headers: { Authorization: `Bearer ${token}` },
})

JWT の構造

header.payload.signature の3部構成(Base64url)。

JWT の保存場所

Refresh Token パターン

  1. Access Token(短命、5〜15分)+ Refresh Token(長命、数日〜数週)
  2. API は Access Token で叩く
  3. Access が切れたら Refresh Token で新しい Access を取得
  4. Refresh Token はHttpOnly Cookieに置いて XSS 耐性

セッション(Cookie + サーバ DB)

  1. ログイン成功時、サーバが session_id を発行
  2. DB / KV / Redis に { session_id: { userId, expires } }
  3. クライアントには session_id だけ Cookie で送信
  4. 毎リクエストでサーバが DB を引いてユーザー特定

メリット: 失効を即時できる(DB から消すだけ)
デメリット: 毎リクエスト DB アクセス

OAuth 2.0 / OIDC(概要)

外部サービス(Google / GitHub / Apple)でログイン。

  1. ユーザーがログインボタンクリック
  2. プロバイダの認可画面にリダイレクト(https://accounts.google.com/...
  3. ユーザーが許可
  4. プロバイダがcallback URLcode を渡す
  5. サーバが codeaccess_token に交換
  6. access_token でユーザー情報を取得
  7. 自社のセッション / JWT を発行

PKCE(モバイル / SPA で必須)

Proof Key for Code Exchangecode_verifiercode_challenge で 途中経路で code が盗まれても安全に。

主要プロバイダ

WebAuthn / Passkeys

パスワードを使わない認証。FIDO2 / WebAuthn標準。Apple / Google / Microsoft が推進。

// 登録
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: ...,
    rp: { name: "My App", id: "example.com" },
    user: { id: ..., name: "user@example.com", displayName: "User" },
    pubKeyCredParams: [{ type: "public-key", alg: -7 }],
    authenticatorSelection: { userVerification: "required" },
  },
})

// 認証
const assertion = await navigator.credentials.get({
  publicKey: { challenge: ..., allowCredentials: [...] },
})

サーバ側ライブラリ: SimpleWebAuthn。プロバイダ統合: Passage / Hanko

CSRF 対策

XSS 対策(Cookie 保護のため)

3rd-party Cookie の終焉

CHIPS(Cookies Having Independent Partitioned State)

Set-Cookie: id=123; SameSite=None; Secure; Partitioned

埋め込み iframe ごとにパーティション化された Cookie を持てる。

認証ライブラリ・SaaS

サービス特徴
ClerkUI 込みフルマネージド。React / Next.js で楽
Auth0古参の定番。エンタープライズ機能豊富
Supabase AuthSupabase の一部。OAuth / Magic Link / Passkey
WorkOSB2B SSO(SAML / SCIM)に強い
Better Auth新興。Hono / Next.js / TanStack 連携
NextAuth (Auth.js)OSS。Next.js 中心だが他にも対応
Lucia軽量・自前実装寄り
Cloudflare AccessCF Workers/Pages 環境向け
最低限の認証チェックリスト

✓ HttpOnly Cookie + SameSite=Lax / Bearer + 適切な保存場所
✓ HTTPS / Secure 属性
✓ パスワードは bcrypt / scrypt / argon2 でハッシュ
✓ レート制限(ブルートフォース対策)
✓ 2FA / Passkey / SSO の対応
✓ ログアウトでセッション無効化
✓ XSS / CSRF 対策