OAuth2刷新令牌轮换失败导致令牌被盗
OAuth2 refresh token rotation failure allows token theft
ID: security/oauth2-refresh-token-rotation-failure-allows-token-theft
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| OAuth2.0 | active | — | — | — |
| Spring Security 5.6+ | active | — | — | — |
| Keycloak 21.0.0 | active | — | — | — |
| Okta 2023.07.0 | active | — | — | — |
根因分析
当未实现刷新令牌轮换时,被盗的刷新令牌无限期有效,使攻击者能够获取新的访问令牌而不被发现。
English
When refresh token rotation is not implemented, a stolen refresh token remains valid indefinitely, allowing an attacker to obtain new access tokens without detection.
官方文档
https://datatracker.ietf.org/doc/html/rfc6749#section-10.4解决方案
-
Implement refresh token rotation: issue a new refresh token each time the old one is used, and invalidate the old token. Example in Spring Security: configure oauth2Client with refreshTokenRotationEnabled(true).
-
Implement refresh token reuse detection: if a revoked refresh token is used, revoke all tokens for that user and alert. Example in Keycloak: enable 'Revoke Refresh Token' in client settings.
-
Set a maximum refresh token lifetime (e.g., 24 hours) and force re-authentication after expiry, combined with rotation.
无效尝试
常见但无效的做法:
-
70% 失败
Setting a short access token lifetime (e.g., 5 minutes) does not protect against refresh token theft because the attacker can still use the refresh token to get new tokens repeatedly.
-
60% 失败
Revoking all tokens on logout is insufficient if the attacker already has the refresh token and uses it before logout.
-
50% 失败
Using a single refresh token with a long lifetime is the default in many OAuth2 implementations, which directly enables this vulnerability.