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

我将自己的云功能部署到 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 := baseUrl

credentials, 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"


守候你守候我
浏览 162回答 2
2回答

守着一只汪

在深入研究了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))}

呼啦一阵风

我编写了一个名为token-generator的开源应用程序。它在 Go 中,我生成签名身份令牌,以便能够调用私有 Cloud Run 和 Cloud Function。随意使用它或复制您自己的应用所需的核心代码!如果您愿意,我们可以在这里讨论或在 GitHub 上打开一个问题。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go