Skip to content

Token、JWT 与刷新撤销 ​

Token 是凭据或授权结果的载体,不规定其内部格式。随机字符串可以引用服务端记录,JWT 则携带结构化声明;选择格式之前,需要先确定谁签发、谁接受、可以访问什么,以及何时停止接受。

区分令牌用途与格式 ​

令牌接收方与用途主要边界
Access Token资源服务器,访问指定 API受众、权限范围、有效期
Refresh Token授权服务器,申请新令牌客户端、授权范围、刷新链与撤销
ID TokenOIDC 客户端,确认认证结果客户端受众、认证事务与身份
恢复令牌账号恢复入口,完成特定动作单次、用途、账号与短有效期

ID Token 不作为通用 API Access Token,Refresh Token 不发给业务 API。API 不应因为某段字符串可以解码成 JWT,就认为它适用于当前接口。

随机不透明令牌便于集中检查活动状态,代价是查询。JWT 可由 API 本地验证,代价是负载更大、密钥管理与状态滞后。OAuth introspection 与撤销分别由 RFC 7662和 RFC 7009定义,令牌是否自包含并不决定它必须采用哪种查询方式。

JWT 的签名与声明 ​

常见签名 JWT 使用三个以点号分隔的部分:JOSE Header、Claims、签名或 MAC。Base64url 编码不是加密,普通签名 JWT 的内容可被持有者读取。RFC 7519也允许使用 JWE 保护机密性,不能把“JWT”一概等同于三段式明文负载。

以下仅是 Access Token 的示意声明,不是已签发的可用令牌:

json
{
  "iss": "https://identity.example.com",
  "sub": "user_123",
  "aud": "orders-api",
  "client_id": "mobile-app",
  "scope": "orders:read",
  "iat": 1793318400,
  "exp": 1793319000,
  "jti": "token_7d6f"
}

exp 和 iat 使用 Unix 秒数;示例给出 10 分钟有效期,只用于说明时间关系。不要混用毫秒,也不要默认所有声明都由任意 JWT 标准强制要求。应用应选择并固定验证配置;采用 OAuth JWT Access Token profile 时,按 RFC 9068处理其必需声明与 typ。

验证顺序 ​

依据 RFC 8725,验证器需要固定可接受算法、密钥来源、签发者、受众和令牌用途,防止算法替换与跨用途混用。

工程上可按下列边界配置成熟库:

  1. 限制输入长度与结构,不允许无界嵌套或超大声明。
  2. 使用配置的算法集合和签发者对应密钥验证密码学保护。
  3. 校验 iss、aud、exp,并按选定 profile 检查其他必需声明。
  4. 处理 nbf、允许的时钟偏差与令牌类型,拒绝不符合当前用途的令牌。
  5. 将已验证主体交给业务授权,检查账号、成员和对象状态。

Header 中的 kid 是密钥选择提示,不是信任依据;不根据任意 jku、x5u 或 kid 去访问攻击者指定的 URL、文件或数据库表达式。共享 HMAC 密钥意味着每个验证方也具备签发能力;多个独立 API 场景通常更适合由签发方保管私钥、验证方持有公钥。

Refresh Token 轮换 ​

RFC 9700 §4.14要求公共客户端的 Refresh Token 使用发送方约束或轮换等规定的保护方式。轮换时每次刷新得到新 Refresh Token,旧值再次出现可作为重放信号。

建议每台设备或每次授权使用独立刷新族,记录 family_id、令牌摘要、账号、客户端、状态、父子关系和绝对期限。下图是一种事务设计,不是标准指定的表结构;它选择在重用时撤销刷新族。

令牌记录和刷新族的锁定或条件更新需要遵守一致的并发协议,防止刷新与撤销同时创建出可用后继。图中的数据库只保存令牌摘要,R1、R2 的原始值不进入普通日志。

数据库无法分辨重用一定来自攻击者。两个标签页同时刷新、网络重试或客户端丢失响应,也可能触发同一现象。

并发刷新与响应丢失 ​

客户端应采用单次在途刷新:同一设备同一时刻只有一个刷新请求,其他请求等待结果。浏览器多标签页还需要跨页协调,不能只在每个页面各设一把内存锁。

如果事务已提交但响应丢失,客户端只持有旧令牌。可选择要求重新登录,或设计严格绑定客户端与幂等请求的短期结果重放机制。后者需要受保护地保留可重发结果,增加秘密存储与泄露面;不能用无限接受旧 Refresh Token 来解决。

删除所有 used 记录会丢失重用检测证据,应按刷新族有效期与审计需求清理。Refresh Token 原始值也不能写入普通数据库日志、链路追踪或错误上报。

撤销与权限变更 ​

机制生效方式代价
短期 Access Token等待过期有明确残余窗口
在线 introspectionAPI 查询当前状态可用性、延迟与缓存一致性
令牌或会话撤销列表查询 jti 或登录实例存储与查询负担
账号安全版本比较当前版本需获得足够新的版本状态
撤销 Refresh Token阻止继续刷新已有 Access Token 通常仍需额外处理

权限变化后,即使旧 Access Token 仍有效,资源服务也可以重新查询成员和对象权限。不能把“签名有效”和“当前业务允许”合并成一个判断。

密钥轮换与泄露 ​

正常轮换先发布新公钥,让验证方有机会获取,再切换签名私钥;保留旧公钥直到旧令牌及允许的时钟偏差窗口结束。验证方对未知 kid 的刷新要限频,防止攻击者触发无界远程请求。

私钥泄露需要紧急拒绝旧密钥,不能机械等待自然过期。对于不再查询签发方的 API,必须有密钥失效传播与缓存刷新机制。JWKS 拉取失败时可按明确策略使用尚可信的缓存,未知密钥不能降级跳过签名。

参考资料 ​