Проверка подлинности звонка клиента в облачную функцию в Golang с использованием учетной записи службы - PullRequest
0 голосов
/ 26 апреля 2020

Я развернул собственную облачную функцию в 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"

Ответы [ 2 ]

1 голос
/ 27 апреля 2020

Через некоторое время углубившись в Oauth-протокол Google и OAuth2 , я обнаружил, что библиотека в Golang не полностью соответствует протоколу OAuth2 от Google.

  • Поток в спецификации Google c: Создать и подписать JWT в HTTP-клиенте (используя учетную запись службы) -> отправить на сервер Google -> получить новый подписанный JWT -> использовать новый токен для других запросов
  • Golang lib: Создать и подписать JWT -> использовать этот токен для других запросов

Удивительно, что библиотека Nodejs правильно обрабатывает поток, тогда как библиотека Golang не. Я подвел итоги своего расследования в сообщении в блоге .

Для тех, кто хочет получить короткий ответ, вот моя реализация (я переместил некоторые части в общедоступный репозиторий c):

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))
}

0 голосов
/ 26 апреля 2020

Я написал приложение с открытым исходным кодом под названием token-generator . Он находится в Go, и я генерирую подписанный токен идентификации для возможности вызова частного Cloud Run и Cloud Function.

Не стесняйтесь использовать его или скопировать основной код, который вам нужен для вашего собственного приложения !! Мы можем обсудить здесь или открыть вопрос на GitHub, если вы предпочитаете.

...