コンテンツにスキップ

面接問題:RESTはステートレスなのにどうやってセッションと認証を実現するか

問題

If REST APIs are stateless, how do authentication and sessions work?

解答

REST の「ステートレス」とは「サーバーがクライアントのセッション情報を保持しない」という意味。認証情報は 毎回リクエストと一緒に送る ことで解決する。

方法 1: JWT(JSON Web Token)— 最も一般的

# ログイン
POST /auth/login
{"email": "user@example.com", "password": "..."}

# レスポンス
HTTP 200 OK
{"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMjN9.xxx"}

# 以後のリクエスト: 毎回 Authorization ヘッダにトークンを添付
GET /api/users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMjN9.xxx
JWT の仕組み:
  Header.Payload.Signature

  Payload に user_id, role, 有効期限 を埋め込む
  → サーバーは DB を引かずにトークンを検証できる(ステートレス!)
  → 署名で改ざん検知
従来のセッション管理(分散環境では注意):
  1. ログイン → サーバーが session_id を生成し Cookie に Set-Cookie
  2. 次のリクエストで Cookie を自動送信
  3. サーバーが session_id を使って Redis/DB からセッションを取得

問題: セッション情報がサーバー側にある(ステートフル)
解決: セッションを Redis に集約 → どのサーバーに当たっても同じセッションを参照可能

方法 3: API Key

# シンプルで恒常的なアクセスに使用(ユーザー認証よりサービス間通信向け)
GET /api/data
X-API-Key: sk-xxxxxxxxxxxx

JWT vs Session の比較

JWT Session
状態 ステートレス(DB 不要) ステートフル(DB/Redis 必要)
スケーラビリティ 高い(どのサーバーでも検証可能) Redis を共有すれば水平スケール可能
トークン無効化 難しい(有効期限まで有効) 簡単(DB から削除するだけ)
サイズ 大きい(Base64 エンコード) 小さい(session_id のみ)

実務でよく使う設計

Access Token  (JWT, 15〜60分) → ステートレス検証
Refresh Token (opaque, 30日) → DB に保存(失効制御のため)

認証フロー:
  Access Token 期限切れ → Refresh Token で新しい Access Token を取得
  ログアウト → Refresh Token を DB から削除(Access Token は有効期限まで使えるが短い)

面接でのポイント

  • 「ステートレス = トークンをクライアントが持ち、毎回送る」という本質を説明できる
  • JWT の署名検証の仕組み(改ざんできない理由)を説明できる
  • JWT の弱点(無効化が難しい)と対策(短い有効期限 + Refresh Token)を言える