コンテンツにスキップ

面接問題:JWTがランダムトークンではなくペイロードを含む設計理由とトレードオフ

問題

As a developer, have you ever thought: Why does JWT include payload data instead of just being a random token?

解答

JWT がペイロードを含む理由:ストレージへのラウンドトリップをなくすため(ステートレス性)

ただし、この設計は一貫性問題というトレードオフを生む。

解説

JWT vs ランダムトークンの比較

ランダムトークン(セッションID方式):
  クライアント → トークン送信 → サーバー → DBで検索 → ユーザー情報取得
  ↑ 毎リクエストにDBアクセスが発生

JWT(Self-Contained):
  クライアント → JWT送信 → サーバー → 署名検証だけでユーザー情報を取得
  ↑ DBへのラウンドトリップが不要 → スケールしやすい

JWT の構造

Header.Payload.Signature

Header:  { "alg": "HS256", "typ": "JWT" }
Payload: { "sub": "user123", "role": "admin", "exp": 1720000000 }
Signature: HMACSHA256(base64(header) + "." + base64(payload), secret)

ペイロードは Base64 エンコードされているだけで暗号化ではない。 機密情報(パスワード・クレカ番号)は絶対に入れてはならない。

一貫性問題(最重要トレードオフ)

問題シナリオ:
  1. ユーザーに admin 権限を付与 → JWT 発行
  2. 不正を検知して admin 権限を剥奪
  3. しかし既発行の JWT はまだ有効期限内
  → ユーザーは剥奪された権限で引き続きアクセスできてしまう

解決策:
  A. 有効期限を短くする(15分 ~ 1時間)
     → 権限変更が遅れて反映されるが被害範囲は小さい
  B. ブラックリストを持つ(Redis に revoked tokens を保存)
     → ラウンドトリップが発生するが即時無効化できる
  C. Refresh Token + Short-lived Access Token の組み合わせ
     → 実務で最も採用されているパターン

実装例(Go)

// JWT 生成
func GenerateToken(userID string, role string) (string, error) {
    claims := jwt.MapClaims{
        "sub":  userID,
        "role": role,
        "exp":  time.Now().Add(15 * time.Minute).Unix(),
        "iat":  time.Now().Unix(),
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString([]byte(os.Getenv("JWT_SECRET")))
}

// JWT 検証
func ValidateToken(tokenStr string) (jwt.MapClaims, error) {
    token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) {
        if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method")
        }
        return []byte(os.Getenv("JWT_SECRET")), nil
    })
    if err != nil || !token.Valid {
        return nil, err
    }
    return token.Claims.(jwt.MapClaims), nil
}

面接でのポイント

  • 「ステートレスでスケールしやすい」だけ答えると浅い
  • 一貫性問題(権限剥奪が即時反映されない) を言及すると深さが出る
  • Refresh Token パターンの説明ができると実務経験として評価される
  • ペイロードは暗号化でなく Base64 エンコードという点も必ず触れる