Remember me 機能の設計 - 長期ログインを安全に扱う

中級 | 13分 で読める | 2026.06.27

公式ドキュメント

Remember me は通常セッションの延長ではない

Remember me は、「ブラウザを閉じてもログイン状態を長く保つ」機能です。

重要なのは、通常の短命セッションを無限に伸ばすのではなく、長期ログイン用の別トークンとして設計することです。

通常セッション:

短命
操作中のログイン状態を表す
サーバー側セッションストアで管理する

Remember me:

長命
新しいセッションを再発行するための入口
端末単位で管理する
盗難時の失効と検知を考える

同じ session_id を30日や90日伸ばすだけだと、盗まれたときの影響範囲が大きくなります。

基本フロー

ログイン時に「ログイン状態を保持する」を選んだ場合、2種類のCookieを発行します。

Set-Cookie: session_id=short_session; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=7200
Set-Cookie: remember_token=long_token; Path=/auth/remember; HttpOnly; Secure; SameSite=Lax; Max-Age=2592000

役割:

Cookie役割期限
session_id通常のログイン状態短い
remember_tokenセッション再発行用長い

通常の画面アクセスでは session_id を使います。session_id が切れていて、remember_token が有効な場合だけ、新しい session_id を発行します。

session_id 有効
  -> そのままログイン済み

session_id 期限切れ / なし
remember_token 有効
  -> remember token を検証
  -> 新しい session_id を発行
  -> remember token もローテーション

DBにはハッシュだけ保存する

Remember token は、パスワードに近い秘密値です。DBには平文で保存しません。

発行する値:

raw_token = ランダムな長い文字列
token_hash = hash(raw_token)

DBに保存:

CREATE TABLE remember_tokens (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL,
  token_hash TEXT NOT NULL UNIQUE,
  device_label TEXT,
  user_agent_hash TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  last_used_at TIMESTAMPTZ,
  expires_at TIMESTAMPTZ NOT NULL,
  revoked_at TIMESTAMPTZ
);

Cookieに入れるのは raw_token、DBに残すのは token_hash です。DBが漏れても、そのままCookieとして使えない状態にします。

ローテーションする

長期トークンは、使うたびに入れ替えます。

1. Cookieのremember_tokenを受け取る
2. hashしてDBを検索する
3. 有効期限とrevoked_atを確認する
4. 新しいremember_tokenを発行する
5. 古いtokenをrevokedにする
6. 新しいsession_idを発行する

これにより、古いトークンを盗まれても、次回利用時に検知しやすくなります。

怪しい例:

古いremember_tokenが、すでにローテーション済みなのに再利用された

この場合、盗難や二重利用の可能性があります。対象ユーザーのRemember tokenを全失効し、再ログインを求める判断ができます。

端末単位で管理する

Remember me は端末単位で扱うのが自然です。

管理画面では、次のような表示ができます。

項目
端末名Chrome on macOS
最終利用2026-06-27 10:30
作成日時2026-06-01 09:00
IPの目安Tokyo, JP
操作この端末をログアウト

端末単位にしておくと、「この端末だけログアウト」「全端末ログアウト」「見覚えのない端末を削除」が実装しやすくなります。

Path を狭くする

Remember token は、通常のAPIや画面アクセスに毎回送る必要がありません。

Set-Cookie: remember_token=...; Path=/auth/remember; HttpOnly; Secure; SameSite=Lax

Path=/auth/remember のように狭くすると、通常の /api/orders/dashboard には送られません。漏洩面を少し小さくできます。

ただし、実装が複雑になる場合は、まず正しい失効・ローテーション・HttpOnly・Secureを優先します。

盗難時に何が起きるか

Remember token が盗まれると、攻撃者は新しいセッションを作れる可能性があります。

対策:

  • tokenは長くランダムにする
  • DBにはハッシュだけ保存する
  • 使用時にローテーションする
  • 再利用を検知する
  • 端末単位で失効できるようにする
  • パスワード変更時に全Remember tokenを失効する
  • 重要操作では再認証を求める

Remember me は便利ですが、長期の認証入口を増やす機能でもあります。管理画面、決済、個人情報変更では、Remember meで復帰しただけの状態から追加確認を入れる設計もあります。

通常セッションとの違い

観点通常セッションRemember token
目的操作中のログイン状態セッション再発行
期限短い長い
送信頻度多い必要なときだけが望ましい
失効単位セッション端末
盗難時の影響期限まで操作可能新しいセッションを作られる可能性

Remember token を「長いsession_id」として扱わないことが大事です。

実装チェックリスト

  • 通常セッションとRemember tokenを分けている
  • Remember tokenは十分に長いランダム値
  • DBにはハッシュだけ保存している
  • 使用時にトークンをローテーションしている
  • 古いトークンの再利用を検知できる
  • 端末単位で失効できる
  • パスワード変更時に全失効できる
  • HttpOnly / Secure / SameSite を設定している
  • 重要操作では再認証を検討している

まとめ

Remember me は便利な機能ですが、認証の長期入口です。

通常セッションを長くするのではなく、長期トークンで新しい短命セッションを再発行する設計にすると、安全性と使いやすさのバランスを取りやすくなります。

参考リソース

次に読む記事

← 一覧に戻る
PR
PR
PR
PR