谷歌API调用时token意外被撤销返回'invalid_grant'错误如何解决
核心原因说明
invalid_grant错误本质为请求提交的授权凭证(授权码、refresh token)无效或已过期,结合你提到的多用户非同时触发的特征,可按照以下优先级排查:
1. 首先排查OAuth同意屏幕发布状态
如果你的谷歌云项目OAuth同意屏幕处于测试模式,所有生成的refresh token有效期只有7天,到期后自动失效,会直接返回该错误。如果是正式使用需要将同意屏幕发布为正式版,无需谷歌审核的场景下发布后refresh token就不会有7天过期限制。
2. 检查refresh token存储逻辑(你场景的最高概率原因)
你当前的认证请求携带了approval_prompt=force参数,每次用户重新授权都会生成新的refresh token,而谷歌对单个用户+单个客户端ID的refresh token有最多50个的数量上限,超过后最早生成的refresh token会被自动作废。
如果你的系统没有做「同一用户新授权后覆盖存储旧refresh token」的逻辑,存量的旧token在使用时就会随机触发该错误,完全符合你描述的多用户非同时触发特征。
3. 检查用户侧主动失效场景
以下用户操作也会导致已下发的refresh token作废:
- 用户在谷歌账号的「安全-第三方应用访问权限」中手动撤销了你的应用授权
- 用户修改了谷歌账号密码
- 用户连续6个月未使用你的应用,谷歌会自动回收对应refresh token
4. 校验请求格式正确性
你当前的token请求、refresh token请求都是POST类型,但你将所有参数放在了URL查询串中,这不符合谷歌OAuth接口规范,POST请求的参数需要放在请求体中,使用application/x-www-form-urlencoded格式提交,参数放在URL中可能会出现截断、转义错误、被代理缓存等问题,偶发触发该错误。
正确的refresh token请求示例:
POST https://oauth2.googleapis.com/token Content-Type: application/x-www-form-urlencoded refresh_token=<refresh_token>&client_id=<client_id>&client_secret=<client_secret>&grant_type=refresh_token
5. 排除速率限制问题
如果你的系统短时间内大量发起refresh token请求,会触发谷歌的接口限流,临时返回invalid_grant错误,可添加指数退避重试逻辑,首次重试等待1s,后续每次翻倍等待时长,最多重试3-5次即可。
内容的提问来源于stack exchange,提问作者Sagarkumar Unhale

