デバイスごとのログアウトとトークンスコープ設計¶
原文¶
ユーザーが1つのデバイスからログアウトしても、別のデバイスではログイン状態が維持される。 これは正しい設計か? トークンはデバイス単位でスコープすべきか?
要約¶
マルチデバイス環境でのセッション管理の設計問題。1台からログアウトしても他のデバイスに影響しないのは意図的な設計か、セキュリティ上の問題か。
回答¶
はい、これは正しい設計です。 トークンはデバイス単位でスコープすべき。ただし、「全デバイスからログアウト」機能も併せて提供するのがベストプラクティス。
解説¶
なぜこの質問が重要か¶
セッション管理はセキュリティの根幹。設計を誤ると、ユーザーのアカウントが不正利用されたとき対処できなくなる。
トークン管理の2つのアプローチ¶
1. グローバルトークン(非推奨)¶
問題点: - 1台でログアウトすると全デバイスが巻き添え → UXが悪い - トークンが1つなので、漏洩時のリスクが大きい - デバイスごとの制御ができない(例: 不審なデバイスだけ無効化できない)
2. デバイス単位トークン(推奨)¶
ユーザーA:
スマホ → token_device_001 (有効)
PC → token_device_002 (有効)
タブレット → token_device_003 (有効)
スマホからログアウト:
スマホ → token_device_001 (無効化)
PC → token_device_002 (有効のまま)
タブレット → token_device_003 (有効のまま)
利点: - 1台のログアウトが他に影響しない → 良いUX - 不審なデバイスだけ選択的に無効化できる - デバイスごとのアクセス履歴を追跡できる
実装パターン¶
JWTベースの場合¶
// トークン発行時にデバイスIDをペイロードに含める
{
"user_id": "user_123",
"device_id": "device_abc", // デバイス固有ID
"iat": 1712900000,
"exp": 1713504800
}
課題: JWTはステートレスなので、個別無効化が難しい。解決策は以下の通り:
-
ブラックリスト方式: ログアウト時にトークンIDをRedis等に登録。検証時にブラックリストを確認
-
リフレッシュトークン方式: アクセストークンは短命(15分)、リフレッシュトークンはDB管理
セッションベースの場合¶
DB: sessions テーブル
| session_id | user_id | device_info | created_at | active |
|------------|----------|-------------------|------------|--------|
| sess_001 | user_123 | iPhone 15, Safari | 2026-04-12 | false | ← ログアウト済み
| sess_002 | user_123 | Chrome, Windows | 2026-04-10 | true |
セッションベースならDBから該当セッションだけ削除/無効化すれば良いのでシンプル。
「全デバイスからログアウト」機能¶
パスワード変更やアカウント侵害時には全デバイスからのログアウトが必要。これは以下で実現する:
// パスワード変更時
1. 該当ユーザーの全リフレッシュトークンを revoked = true に
2. または全セッションを active = false に
3. 各デバイスは次のトークンリフレッシュ時にログアウトされる
Googleの実装例¶
Googleのセキュリティ設定画面では: - ログイン中のデバイス一覧を表示 - 個別デバイスのセッションを終了できる - 「すべてのデバイスからログアウト」も可能 - 不審なアクティビティがあるデバイスを警告
これがデバイス単位トークン管理のベストプラクティスの好例。
面接で差がつくポイント¶
- 「正しい設計か?」に対して Yes/Noだけでなくトレードオフを説明 できる
- JWTのステートレス性と個別無効化の矛盾をどう解決するか説明できる
- 「全デバイスログアウト」の必要性(セキュリティインシデント対応)にも言及できる
- 実際のサービス(Google、GitHub等)の実装を例に挙げられる