JWTリフレッシュトークンの仕組み
JWTリフレッシュトークンの動作原理、短期アクセストークンとの組み合わせ方、ローテーション戦略、安全な保存方法、トークン更新フローの実装を解説します。
詳細な説明
リフレッシュトークンは、ユーザーに再認証を要求せずに新しいアクセストークンを取得するために使用される長期間有効な認証情報です。JWTベースの認証システムでは、短期間のアクセストークンと長期間のリフレッシュトークンの組み合わせにより、セキュリティとユーザー体験のバランスを実現します。
トークンペアパターン:
Login Response:
{
"access_token": "eyJhbGc...", // 短期間(5〜15分)
"refresh_token": "dGhpcyBp...", // 長期間(数日〜数週間)
"expires_in": 900
}
アクセストークンが期限切れになると、クライアントは専用のエンドポイント(例: POST /auth/token/refresh)にリフレッシュトークンを送信して新しいアクセストークンを受け取ります。これはユーザーに透過的に行われ、認証情報の再入力なしにセッションを維持します。
なぜ長期間のアクセストークンだけではダメなのか?
長期間のアクセストークンが盗まれると、攻撃者に長期間のアクセスを与えることになります。短期間のアクセストークンはダメージウィンドウを数分に限定します。リフレッシュトークンは認証サーバーにのみ送信され(リソースAPIには送信されない)、露出面が減少します。アクセストークンが漏洩しても、すぐに期限切れになります。リフレッシュトークンが漏洩しても、サーバーサイドで失効させることができます。
リフレッシュトークンのローテーション:
ベストプラクティスはリフレッシュトークンのローテーションを実装することです。リフレッシュトークンが使用されるたびに、サーバーは新しいリフレッシュトークンを発行し、古いものを無効化します。攻撃者がリフレッシュトークンを盗んで使用すると、正規ユーザーの次のリフレッシュ試行が失敗し(古いトークンが無効化されているため)、潜在的な侵害を示すシグナルとなります。これは「自動再利用検出」と呼ばれることがあります。サーバーは再利用が検出された場合、リフレッシュトークンファミリー全体を無効化すべきです。
保存とセキュリティ:
リフレッシュトークンは安全に保存する必要があります。ブラウザでは、JavaScriptからアクセスできないHttpOnly Cookieが、XSS攻撃から保護するためlocalStorageよりも推奨されます。モバイルアプリでは、iOS KeychainやAndroid Keystoreなどのセキュアストレージメカニズムを使用してください。リフレッシュトークンはクライアントにバインドすべきです。サーバーはクライアントのフィンガープリント(IP、User-Agent、またはデバイスID)を記録し、異なるコンテキストからのリフレッシュ試行を拒否します。
サーバーサイドトラッキング:
アクセストークンとは異なり、リフレッシュトークンは通常データベースに保存されます。これにより失効が可能になり、これがリフレッシュトークンパターンの主な利点です。ユーザーがログアウト、パスワード変更、または無効化された場合、サーバーはリフレッシュトークンを削除し、新しいアクセストークンの発行を防ぎます。
ユースケース
モバイルバンキングアプリが5分間のアクセストークンと30日間のリフレッシュトークンを使用し、ユーザーのログイン状態を維持しつつ、盗まれたアクセストークンがすぐに期限切れになることを保証します。