如何通过curl完成OAuth认证访问已部署的Google Cloud Functions
解决方案
你之前参考的Web Server OAuth2文档不适用于服务账号非交互式调用Cloud Functions的场景,服务账号服务到服务的调用不需要交互授权流程,也不需要单独申请client_id和client_secret,直接使用服务账号密钥即可完成认证,具体操作如下:
前置检查
- 确认调用端使用的服务账号已经被授予
roles/cloudfunctions.invoker权限,该权限是访问受IAM保护的Cloud Functions的必要前提 - 下载该服务账号的JSON格式密钥文件,保存到调用端本地,后续操作均基于该密钥文件
方案1:调用端可安装gcloud CLI(操作最简单)
直接通过gcloud生成身份令牌,拼接curl命令即可完成调用:
curl -H "Authorization: Bearer $(gcloud auth print-identity-token --audience=<你的Cloud Functions完整触发URL>)" <你的Cloud Functions完整触发URL>
如果调用端没有用该服务账号做过身份认证,先执行一次激活命令即可:
gcloud auth activate-service-account --key-file=<本地服务账号密钥文件路径>
方案2:调用端无法安装gcloud(纯REST接口调用)
不需要依赖任何GCP工具,直接通过通用HTTP请求完成认证,全程非交互式:
步骤1:生成签名JWT
使用服务账号密钥文件中的private_key、client_email字段构造JWT,具体参数如下:
- 签名算法:固定为RS256
- Header参数:
alg: RS256,typ: JWT - Payload参数:
- iss:填服务账号的
client_email值 - sub:和
iss填相同值 - aud:固定填
https://oauth2.googleapis.com/token - target_audience:填你的Cloud Functions完整触发URL
- iat:当前秒级时间戳
- exp:当前秒级时间戳+3600(令牌最长有效期为1小时)
用服务账号的私钥对上述内容签名,得到完整的JWT字符串。
- iss:填服务账号的
步骤2:用JWT换取访问用身份令牌
执行如下HTTP请求:
curl --request POST \ --url https://oauth2.googleapis.com/token \ --header 'content-type: application/x-www-form-urlencoded' \ --data grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \ --data assertion=<上一步生成的签名JWT字符串>
请求返回结果中的id_token字段就是可用于访问Cloud Functions的身份令牌。
步骤3:访问Cloud Functions
携带身份令牌发起请求即可:
curl -H "Authorization: Bearer <上一步获取的id_token>" <你的Cloud Functions完整触发URL>
问题澄清
- 你之前遇到的跳转错误是误用了面向普通用户登录的OAuth流程,该流程需要浏览器交互授权,天然不适合服务到服务的非交互式调用场景
- 不需要单独维护刷新令牌,身份令牌过期后重新走上述JWT生成、换令牌的流程即可,安全性更高,也完全不需要用到client_secret参数
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

