为了账号安全,请及时绑定邮箱和手机立即绑定

使用服务帐户在 Golang 中验证对 Cloud Function 的客户端调用

使用服务帐户在 Golang 中验证对 Cloud Function 的客户端调用

Go
守候你守候我 2022-06-01 12:27:23
我将自己的云功能部署到 GCP。在云功能上,我启用了使用 Google 服务帐户进行身份验证。我需要编写一个 Golang 代码来调用这个云函数。我用 Nodejs 完成了同样的目的,但不能让 Golang 工作。这是我的 Nodejs 代码(工作):const {GoogleAuth} = require('google-auth-library');const targetAudience = "cloud-function-url"async function run() {    const auth = new GoogleAuth();    const client = await auth.getIdTokenClient(targetAudience);    const res = await client.request({ url });    console.info(res.data);}我的 Golang 代码:import  "golang.org/x/oauth2/google"func getToken() (err error) {    scope := "https://www.googleapis.com/auth/cloud-platform"    client, err := google.DefaultClient(context.Background(), scope)    if err != nil {        return    }    res, err := client.Get("cloud-function-url")    if err != nil {        return    }    fmt.Println(res)    return}我也尝试自定义要添加的代码targetAudience,但它也不起作用baseUrl := "your-cloudfunction-baseurl"ctx := context.Background()targetAudience := baseUrlcredentials, err := google.FindDefaultCredentials(ctx)if err != nil {    fmt.Printf("cannot get credentials: %v", err)    os.Exit(1)}tokenSrc, err := google.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)if err != nil {    fmt.Printf("cannot create jwt source: %v", err)    os.Exit(1)}client := oauth2.NewClient(context.Background(), tokenSrc)if err != nil {    return}res, err := client.Get(baseUrl + "sub-url")if err != nil {    return}我已检查并确保我的服务帐户已正确加载。在上述两种情况下,我都收到了401 "The access token could not be verified"
查看完整描述

2 回答

?
守着一只汪

TA贡献1872条经验 获得超4个赞

在深入研究了Google 的 Oauth 协议OAuth2之后,我发现 Golang 中的库并没有完全遵循 google 的 OAuth2 协议。

  • 谷歌规范中的流程:在 HTTP 客户端(使用服务帐户)中生成和签署 JWT --> 发送到谷歌的服务器 --> 获取新的签名 JWT --> 将新令牌用于其他请求

  • Golang lib:生成并签署 JWT --> 将此令牌用于其他请求

令人惊讶的是,Nodejs 库正确处理了流程,而 Golang 库却没有。我将我的调查总结为一篇博文

对于那些想要简短回答的人,这是我的实现(我将一些部分移到了公共仓库中):

import (

    "context"

    "fmt"

    "io/ioutil"

    "os"


    "github.com/CodeLinkIO/go-cloudfunction-auth/cloudfunction"


    "golang.org/x/oauth2/google"

)


func main() {

    baseUrl := "your-cloudfunction-baseurl"

    ctx := context.Background()

    targetAudience := baseUrl

    credentials, err := google.FindDefaultCredentials(ctx)

    if err != nil {

        fmt.Printf("cannot get credentials: %v", err)

        os.Exit(1)

    }


    jwtSource, err := cloudfunction.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)

    if err != nil {

        fmt.Printf("cannot create jwt source: %v", err)

        os.Exit(1)

    }


    client := cloudfunction.NewClient(jwtSource)

    res, err := client.Get(baseUrl + "/cloudfunction-sub-page")

    if err != nil {

        fmt.Printf("cannot fetch result: %v", err)

        os.Exit(1)

    }

    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)

    if err != nil {

        fmt.Printf("cannot read response: %v", err)

        os.Exit(1)

    }

    println(string(body))

}


查看完整回答
反对 回复 2022-06-01
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

我编写了一个名为token-generator的开源应用程序。它在 Go 中,我生成签名身份令牌,以便能够调用私有 Cloud Run 和 Cloud Function。

随意使用它或复制您自己的应用所需的核心代码!如果您愿意,我们可以在这里讨论或在 GitHub 上打开一个问题。


查看完整回答
反对 回复 2022-06-01
  • 2 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号