4. 令牌刷新流程详解:Refresh Token Grant 流程、刷新请求的认证与授权、新令牌的签发与旧令牌的失效

OIDC(OpenID Connect)协议中的 Refresh Token Grant 是解决 Access Token 短期过期后无感续期问题的核心机制。该流程涉及客户端、授权服务器、资源服务器以及缓存层的协同工作。本节将深入剖析刷新请求的完整生命周期,包括请求认证、新令牌签发以及旧令牌的失效策略。

4.1 Refresh Token Grant 流程全景

Refresh Token Grant 属于 OAuth 2.0 授权码流程的扩展。当 Access Token 过期(通常为 1 小时),客户端可使用长期有效的 Refresh Token 向授权服务器的 Token 端点发起刷新请求,获取一组新的令牌。整个流程不要求用户重新登录,实现了无感续期。

关键前提: Refresh Token 必须在初始授权码交换时由授权服务器签发,且客户端必须安全存储该令牌。Refresh Token 通常具有较长的有效期(如 7 天或 30 天),但可被撤销或轮换。
Refresh Token Grant 完整流程 Refresh Token Grant 完整流程 客户端 授权服务器 资源服务器 缓存层(Redis) 1. 请求资源(携带过期 AT) 2. 返回 401 Unauthorized 3. POST /token (grant_type=refresh_token) 4. 验证 Refresh Token 签名与状态 5. 签发新 AT + 新 RT(轮换) 6. 返回新 Access Token + Refresh Token 7. 更新缓存(新 AT 映射) 8. 使用新 AT 重试请求 9. 返回 200 OK + 资源

4.2 刷新请求的认证与授权

授权服务器在处理刷新请求时,必须对客户端和 Refresh Token 进行双重验证。验证失败将直接拒绝请求,并返回 invalid_grant 或 invalid_client 错误。

验证维度 验证内容 失败处理
客户端认证 验证 client_id + client_secret(机密客户端)或 client_id(公开客户端) 返回 401,错误码 invalid_client
Refresh Token 有效性 验证签名、是否过期、是否已被撤销 返回 400,错误码 invalid_grant
绑定关系 确认 Refresh Token 与 client_id 匹配,且未超出授权范围 返回 400,错误码 invalid_grant
令牌轮换策略 若启用轮换,检查 Refresh Token 是否已被使用过 撤销所有关联令牌,返回 invalid_grant
安全警示: 如果授权服务器检测到 Refresh Token 被重复使用(即轮换策略下的重放攻击),必须立即撤销该用户/客户端的所有令牌,并触发安全告警。这是防止令牌泄露后持续滥用的关键防线。

4.3 新令牌的签发与旧令牌的失效

当刷新请求通过所有验证后,授权服务器将执行令牌签发与失效操作。这一过程涉及多个组件的状态变更,是缓存失效问题的重灾区。

4.3.1 新令牌签发流程

  1. 生成新 Access Token: 使用当前时间作为 iat,设置新的 exp(通常为 1 小时),保留原始 scope 和 claims。
  2. 生成新 Refresh Token(可选): 若启用轮换策略,生成全新的 Refresh Token;若不轮换,则复用旧 Refresh Token。
  3. 更新持久化存储: 将新令牌的哈希值写入数据库,记录签发时间、客户端 ID、用户 ID。
  4. 更新缓存层: 将新 Access Token 的映射关系写入 Redis,设置与令牌过期时间一致的 TTL。
  5. 返回响应: 返回 200 OK,Body 包含 access_token、refresh_token、token_type、expires_in。
新令牌签发与旧令牌失效时序 新令牌签发与旧令牌失效时序 T0 T+1h 旧 Access Token(有效) 刷新请求到达 新 Access Token(有效) 旧 Refresh Token(轮换后失效) 新 Refresh Token(有效) 缓存层操作:删除旧 AT 映射 → 写入新 AT 映射(TTL=3600s) 若缓存删除失败,旧 AT 在 TTL 内仍可访问,导致缓存不一致

4.3.2 旧令牌失效策略对比

失效策略 实现方式 优点 缺点
黑名单模式 将旧令牌的 jti 加入 Redis 黑名单,TTL 设为原令牌剩余有效期 立即生效,无需等待 TTL 过期 增加缓存存储压力,需额外查询黑名单
TTL 自然过期 不主动删除,等待旧令牌 TTL 到期后自动失效 实现简单,无额外存储开销 存在时间窗口(最长 1 小时),旧令牌仍可被使用
令牌轮换 每次刷新签发新 Refresh Token,旧 Refresh Token 立即失效 防止 Refresh Token 泄露后的重放攻击 增加令牌管理复杂度,需处理并发刷新冲突
版本号递增 在用户/客户端维度维护令牌版本号,旧版本令牌自动失效 批量失效,适合强制登出场景 需要持久化存储版本号,增加数据库查询
生产建议: 推荐采用 令牌轮换 + 黑名单模式 的组合策略。轮换确保 Refresh Token 的一次性使用,黑名单确保旧 Access Token 在刷新后立即失效。同时,在 Redis 中设置合理的 TTL(建议为原令牌剩余有效期),避免黑名单无限膨胀。

4.4 缓存失效的典型故障场景

在令牌刷新过程中,缓存失效是导致认证授权平台故障的最常见原因。以下列出三个高频故障场景及其根因分析:

  • 场景一:缓存删除失败导致旧令牌仍可用
    刷新请求成功签发新令牌,但 Redis 中旧 Access Token 的映射未被删除。客户端使用旧令牌仍能通过资源服务器的缓存校验,造成新旧令牌同时有效,违反安全策略。
  • 场景二:缓存写入延迟导致新令牌无法使用
    授权服务器返回新令牌后,Redis 写入操作因网络抖动或主从同步延迟未完成。客户端立即使用新令牌请求资源,资源服务器查询缓存时找不到映射,返回 401。
  • 场景三:并发刷新导致令牌状态不一致
    客户端在短时间内发起多次刷新请求(如网络重试),授权服务器处理第一次请求后轮换了 Refresh Token,后续请求携带的旧 Refresh Token 被判定为已使用,导致所有令牌被撤销。
诊断要点: 当出现令牌刷新后认证失败时,优先检查 Redis 中 access_token:{jti} 和 refresh_token:{jti} 的键是否存在、TTL 是否正确。同时,查看授权服务器日志中的 grant_type=refresh_token 请求,确认是否触发了令牌轮换冲突。