OAuth/OIDCログイン後に自サービスのsessionを作る流れ

中級 | 13分 で読める | 2026.06.27

公式ドキュメント

外部ログイン後も自サービスのsessionは必要

GoogleログインやGitHubログインを使っても、自サービス側のログイン状態管理は必要です。

OIDCで「この人は誰か」を確認した後、自サービスのユーザーに紐づけ、自サービス用のsessionを発行します。

外部IdPのログイン結果を、そのまま毎リクエストのログイン状態として扱うのではありません。

Googleで本人確認
  -> 自サービスの users と紐づけ
  -> 自サービスの session_id を発行
  -> 以後は自サービスのCookieで認証

全体フロー

OIDCログインの大まかな流れです。

1. ユーザーが「Googleでログイン」を押す
2. 自サービスが state / nonce を作る
3. Googleの認可画面へリダイレクトする
4. Googleが callback URL へ code を返す
5. 自サービスが code を token endpoint で交換する
6. ID Token を検証する
7. 自サービスの users と紐づける
8. 自サービスの session_id を発行する
9. Set-Cookie でブラウザへ保存する

ログイン完了後のレスポンス例:

HTTP/1.1 302 Found
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax
Location: /dashboard

以後の認証は、Googleではなく自サービスの session_id を見ます。

state の役割

state は、ログイン開始リクエストとcallbackを対応させる値です。CSRF対策として重要です。

login start:
  state=random_abc を保存
  Googleへ state=random_abc を送る

callback:
  state=random_abc が戻る
  保存済みstateと一致するか確認

一致しなければ、ログイン処理を中断します。

state は推測できないランダム値にし、短い期限で保存します。保存先は、サーバー側セッション、暗号化Cookie、一時ストアなどです。

nonce の役割

OIDCでは、ID Tokenのすり替え対策として nonce を使います。

login start:
  nonce=random_xyz を保存
  認可リクエストに nonce を含める

callback:
  ID Token内の nonce が random_xyz と一致するか確認

state はリクエスト対応、nonce はID Token対応、と分けて理解します。

主な役割
statecallbackが自分で始めたログインの続きか確認
nonce返ってきたID Tokenがこのログイン用か確認

ID Tokenを検証する

ID Tokenを受け取ったら、最低限次を確認します。

  • 署名が正しい
  • iss が期待する発行者
  • aud が自サービスのclient_id
  • exp が期限内
  • nonce が一致
  • 必要なら email_verified を確認

ID Tokenの中にメールアドレスが入っているからといって、検証せずに信用してはいけません。

users との紐づけ

外部ログイン後は、自サービス内のユーザーを決めます。

例:

CREATE TABLE user_identities (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES users(id),
  provider TEXT NOT NULL,
  provider_subject TEXT NOT NULL,
  email TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (provider, provider_subject)
);

provider_subject は、GoogleなどのIdPが返すユーザー識別子です。メールアドレスは変更される可能性があるため、外部IDの主キーとしては sub を使うのが基本です。

provider = google
provider_subject = ID Token の sub

session発行

ユーザーが確定したら、自サービスのsessionを発行します。

session_id=random
sessions[session_id] = {
  userId: user_001,
  loginMethod: "google",
  authLevel: "oidc",
  loginAt: now
}

HTTPレスポンス:

Set-Cookie: session_id=...; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=7200

以後は、通常のCookieセッションと同じです。

SameSiteで詰まるところ

OIDCログインでは、外部IdPから自サービスへ戻るcallbackがあります。

accounts.google.com -> app.example.com/auth/callback

これは別サイトからのトップレベル遷移です。SameSite=Lax なら、GET callbackではCookieが送られることがあります。POST callbackやiframe、別サイト埋め込みを使う構成では、SameSite=None; Secure が必要になることもあります。

詰まりやすい点:

  • state保存Cookieがcallbackで送られない
  • callbackがPOSTでSameSiteに引っかかる
  • フロントとAPIが別siteでCookieが送られない
  • Secure がなく SameSite=None が拒否される
  • callback URLのドメインが想定と違う

OAuth/OIDCの不具合は、認証ロジックだけでなくCookie属性とリダイレクトの組み合わせで起きます。

外部アクセストークンをsessionに載せすぎない

Google APIを呼ぶためのaccess tokenを、自サービスのブラウザsessionへそのまま露出させるのは避けます。

避けたい設計:

/api/session が Google access_token を返す
ブラウザJSが access_token を保持する

望ましい設計:

ブラウザ -> 自サービスBFF
BFF -> Google API

ブラウザには自サービスのHttpOnly Cookieだけを持たせ、外部APIトークンはサーバー側で管理する設計が安全です。

ログアウト時の注意

自サービスからログアウトしても、Googleからログアウトされるとは限りません。

ログアウトで分けるもの:

対象何をするか
自サービスsession削除する
自サービスCookie削除する
外部refresh token必要なら失効する
Googleアカウント自体通常はログアウトしない

「自サービスからログアウト」と「IdPからログアウト」は別物です。

まとめ

OAuth/OIDCログイン後は、外部IdPで本人確認をしたうえで、自サービス側のユーザーに紐づけ、自サービスのsessionを発行します。

  • state でcallbackの対応を確認する
  • nonce でID Tokenの対応を確認する
  • ID Tokenを検証する
  • sub を使って外部IDと紐づける
  • 自サービスの session_id を発行する
  • SameSiteやcallback URLの条件を確認する
  • 外部access tokenをブラウザへ露出させない

外部ログインを使っても、session設計がなくなるわけではありません。

参考リソース

次に読む記事

← 一覧に戻る
PR
PR
PR
PR