面接問題: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 を引かずにトークンを検証できる(ステートレス!)
→ 署名で改ざん検知
方法 2: Session Cookie + Session Store¶
従来のセッション管理(分散環境では注意):
1. ログイン → サーバーが session_id を生成し Cookie に Set-Cookie
2. 次のリクエストで Cookie を自動送信
3. サーバーが session_id を使って Redis/DB からセッションを取得
問題: セッション情報がサーバー側にある(ステートフル)
解決: セッションを Redis に集約 → どのサーバーに当たっても同じセッションを参照可能
方法 3: API Key¶
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)を言える