# OAuth2刷新令牌轮换失败导致令牌被盗

- **ID:** `security/oauth2-refresh-token-rotation-failure-allows-token-theft`
- **领域:** security
- **类别:** auth_error
- **错误码:** `OAUTH2_REFRESH_TOKEN_ROTATION_FAILURE`
- **验证级别:** ai_generated
- **修复率:** 87%

## 根因

当未实现刷新令牌轮换时，被盗的刷新令牌无限期有效，使攻击者能够获取新的访问令牌而不被发现。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| OAuth2.0 | active | — | — |
| Spring Security 5.6+ | active | — | — |
| Keycloak 21.0.0 | active | — | — |
| Okta 2023.07.0 | active | — | — |

## 解决方案

1. ```
   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).
   ```
2. ```
   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.
   ```
3. ```
   Set a maximum refresh token lifetime (e.g., 24 hours) and force re-authentication after expiry, combined with rotation.
   ```

## 无效尝试

- **** — 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. (70% 失败率)
- **** — Revoking all tokens on logout is insufficient if the attacker already has the refresh token and uses it before logout. (60% 失败率)
- **** — Using a single refresh token with a long lifetime is the default in many OAuth2 implementations, which directly enables this vulnerability. (50% 失败率)
