Google Cloud Tasks调用Cloud Run返回403 PERMISSION_DENIED错误如何解决
问题根源
你遇到的403错误不是Google Cloud Tasks和Cloud Run之间的授权问题,是你的Django API自带的JWT认证逻辑,无法校验Cloud Tasks生成的Google OIDC令牌导致的。
具体解决步骤
- 首先确认Cloud Tasks的令牌传输正常:Cloud Tasks会自动在请求头添加
Authorization: Bearer <OIDC_TOKEN>,你可以在Django接口中先打印收到的Authorization请求头,确认令牌存在且格式正确。 - 你当前返回
invalid token,是因为Django默认的JWT校验逻辑,是用你自己业务系统的签发密钥、签发方规则校验的,而Cloud Tasks生成的OIDC令牌是Google官方签发的,你需要新增一套专门的认证逻辑适配这类令牌,校验规则如下:- 解析收到的JWT令牌头,获取密钥ID(
kid)字段 - 获取Google官方公开的OIDC公钥列表,用
kid对应的公钥校验令牌签名合法性 - 校验令牌的签发方(
iss)为Google官方地址 - 校验令牌的受众(
aud)为你的Cloud Run服务完整URL,和你代码中任务配置的url值完全一致 - 校验令牌的过期时间(
exp)未超时 - 校验令牌中的邮箱(
email)字段,和你配置的GS_Q_IAM_EMAIL服务账号邮箱完全一致
- 解析收到的JWT令牌头,获取密钥ID(
- 校验通过后,你可以直接把该服务账号邮箱当成你的业务系统合法用户:提前在Django后台将这个服务账号邮箱注册为用户,分配对应接口的调用权限,校验通过后直接登录该用户即可完成授权。
疑问澄清
- OIDC令牌本身是用于身份断言,你可以基于它断言的合法身份,在自己的业务系统中完成权限校验,完全可以用于你的场景,不存在不能用的问题。
- OAuth令牌仅支持调用
*.googleapis.com后缀的Google官方接口,你的Cloud Run服务不属于这类接口,所以之前调用报错是正常的,你当前的场景只能使用OIDC方案。 - 不需要给服务账号设置密码,服务账号的身份合法性已经通过Google签发的OIDC令牌的签名校验证明了,不需要额外的账号密码认证。
内容的提问来源于stack exchange,提问作者Niyojan
相关产品推荐
相关产品推荐

