リフレッシュトークンフロー
アクセストークンの有効期限が切れた際に、ユーザーの再認証なしで新しいアクセストークンを取得するフロー。ユーザー体験を向上させつつ、セキュリティを維持します。
トークンローテーション
トークンローテーションは、リフレッシュトークンを使用するたびに新しいリフレッシュトークンを発行し、 古いリフレッシュトークンを無効化するセキュリティ手法です。
初回トークン発行
認可フロー完了時にアクセストークンとリフレッシュトークンRT1が発行される。
トークン更新
RT1でリフレッシュすると、新しいアクセストークンとRT2が発行される。RT1は無効化される。
漏洩検知
攻撃者がRT1を使用すると、既に無効化されているため失敗する。認可サーバーはRT1の不正使用を検知し、RT2も含めて全トークンを無効化できる。
リプレイ検知の仕組み
無効化されたリフレッシュトークンが使用された場合、 そのトークンファミリー全体が侵害されたとみなし、 関連するすべてのトークンを無効化します。 これにより、トークン漏洩時の被害を最小限に抑えられます。
サーバーサイドセッション
HTTPOnly Cookie でセッションIDを管理し、サーバー側でリフレッシュトークンを保存。最も安全。
HTTPOnly Cookie(直接)
Secure、HttpOnly、SameSite=Strict 属性を設定。XSS攻撃からは保護されるが、CSRF対策が必要。
localStorage / sessionStorage
XSS攻撃で容易にアクセスされる。パブリッククライアントでは避けるべき。
シーケンス図
各ステップの詳細
クライアント → 認可サーバー
クライアントがリフレッシュトークンを使用してトークンエンドポイントに新しいアクセストークンを要求します。
リクエスト
POST /token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=refresh_token&refresh_token=dGhpcyBpcyBhIHJlZnJlc2g...&scope=openid profile
セキュリティノート
- !リフレッシュトークンは安全に保存する(サーバーサイド推奨)
- !scope は元のスコープ以下に限定される
- !機密クライアントはクライアント認証が必要
認可サーバー → クライアント
認可サーバーがリフレッシュトークンを検証し、新しいアクセストークン(と場合によっては新しいリフレッシュトークン)を発行します。
リクエスト
POST /token
レスポンス
200 /token
{ "access_token": "eyJhbGciOiJSUzI1NiIs...(新しいトークン)", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "bmV3IHJlZnJlc2ggdG9rZW4...(新しいRT)", "scope": "openid profile" }
セキュリティノート
- !トークンローテーション: 新しいリフレッシュトークンが発行される場合がある
- !古いリフレッシュトークンは無効化される(ローテーション時)
- !トークンローテーションにより漏洩時の被害を限定できる
- +アクセストークンの有効期限が切れた場合
- +長期間のセッション維持が必要な場合
- +ユーザーに再ログインを求めたくない場合
- +オフラインアクセスが必要な場合
- -サーバー間通信 → 新しいアクセストークンを直接取得する
- -短命なセッションのみの場合
- -セキュリティ要件が特に厳しく、毎回認証が必要な場合
セキュリティ上の考慮事項
- !リフレッシュトークンは長命なため、厳格に管理する
- !トークンローテーションを実装して漏洩リスクを軽減する
- !リフレッシュトークン漏洩を検知したら全トークンを無効化する
- !パブリッククライアントではリフレッシュトークンの発行を慎重に検討する
- !リフレッシュトークンにも有効期限を設定する
- !不審なリフレッシュトークンの使用パターンを監視する