接入与联调
令牌交换与刷新
invalid_grant 的排查顺序、刷新令牌为什么会突然失效、scope 为什么少了、令牌校验该用 jwks 还是 introspect。
换令牌时报 invalid_grant
按顺序排查:
| 检查项 | 说明 |
|---|---|
| 授权码是否已经用过 | 授权码一次性,重复使用必然失败 |
| 是否超过有效期 | 授权码有效期很短,取到后应立刻交换 |
code_verifier 与 code_challenge 是否配对 | PKCE 的 S256 结果必须一致 |
redirect_uri 是否逐字一致 | 与授权请求里的值必须完全相同 |
| 客户端认证是否正确 | 机密客户端要用登记的那对凭据 |
完整清单见错误码。
刷新令牌为什么会突然失效
两个原因:
- 轮换:每次刷新都会换发新值,旧值立即作废。两处代码同时拿着同一个旧值刷新,其中一次必然失败;
- 过期:刷新令牌本身有有效期(机密客户端 30 天,公开客户端 14 天)。
并发场景下应把刷新串行化:同一账号同一客户端只允许一个刷新在途。
为什么请求了某个 scope,返回里却没有
服务端会按客户端能力裁剪 scope,裁剪是静默丢弃,不报错。以响应里的 scope 为准,不要以你请求的为准。详见 Scope 与受众。
为什么用访问令牌调 UserInfo 返回 401
最常见的原因是受众不对:UserInfo 只接受 auth 受众的令牌,且 scope 里至少有 openid / profile / email 之一。另一个常见原因是令牌已过期或被撤销。
校验令牌用 jwks 还是 introspect
| 方式 | 适用 | 代价 |
|---|---|---|
jwks 本地校验 | 高频调用、可接受 5 分钟缓存 | 需处理 kid 轮换与时钟偏差 |
introspect | 需要实时撤销状态 | 仅机密客户端可用,每次都请求服务端 |
公开客户端只能走本地校验。