返回博客列表
后端工程2026年8月20日2 分钟阅读

OAuth Token 生命周期:刷新、缓存与敏感信息保护

结合 Tesla Fleet API 接入,复盘 Partner Token、用户授权 Token、刷新轮换与失败重试的边界。

#Go#OAuth 2.0#可观测性

接入第三方 OAuth 时,最容易完成的是授权跳转,最容易留下问题的是授权之后:Token 放在哪里、何时刷新、并发刷新如何合并、401 是否重试、refresh token 轮换如何保存。

区分两类 Token

  • Partner Token 代表应用自身,用于注册合作方和服务间请求

  • Third-party Token 代表用户授权,只能访问用户允许的 scope

  • 两者的 audience、scope、过期时间和存储策略不同

提前刷新而不是等到过期

缓存记录 expiresAt,并预留安全窗口。请求到来时,如果 Token 仍在有效窗口就直接使用;接近过期时只有一个协程执行刷新,其他请求等待同一结果,避免并发击穿授权服务器。

if token.ExpiresAt.Before(time.Now().Add(refreshWindow)) {
    return refresher.Refresh(ctx)
}

401 只重试一次

上游 401 可能表示 Token 被提前吊销。客户端清理缓存、刷新并重试一次;如果仍然失败,就把错误交给调用方。无限重试只会放大故障并隐藏配置问题。

Refresh Token 轮换

部分 OAuth 服务每次刷新都会返回新的 refresh token。保存新 Token 必须是原子操作,成功后旧 Token 立即失效。多实例环境需要共享存储和分布式互斥,同时对持久化内容加密。

浏览器会话

第三方 access token 不直接返回浏览器。浏览器只持有 HttpOnly、Secure、SameSite 合理配置的会话 Cookie,服务端根据会话读取加密后的 Token。

日志规则

Token 可以用于定位问题,但不应该成为日志内容。默认记录请求 ID、上游状态码、错误类型和刷新结果,不记录凭证本身。

明确当前限制

单实例原型使用内存会话是可以接受的,但必须在文档中写清楚:服务重启后需要重新授权,多实例前必须迁移到共享存储。