go - 端点 Google ID JWT 和 Golang oauth2 : have id_token, 需要 access_token?

标签 go oauth-2.0 google-cloud-endpoints

我在端点后面有一个 App Engine 应用程序,但我在遵循有关添加身份验证的文档时遇到了问题。我的偏好是允许项目内的服务帐户通过,然后执行更精细的应用程序端授权。

在我的例子中,大多数客户端将在 GCP 之外并且将是自动化程序而不是人,所以我使用 JSON key 文件认为这是可行的方法(如果我错了请纠正我)。我也不希望必须重新部署应用程序才能更改用户配置,因此我遵循此处文档中的“GOOGLE ID JWT”信息:

https://cloud.google.com/endpoints/docs/openapi/service-to-service-auth

这是我的 swagger JSON 的安全部分:

  "securityDefinitions": {
    "api_key": {
      "type": "apiKey",
      "name": "key",
      "in": "query"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "https://accounts.google.com"
    }
  },
  "security": [
    {
      "api_key": [],
      "google_id_token": []
    }
  ]

部署没问题,但我不知道如何从客户端使用服务帐户 JSON。

在 Go 中,根据我对 oauth2/google 文档的理解,我使用以下内容:

package main

import (
    "context"
    "fmt"
    "io/ioutil"
    "log"
    "os"

    "golang.org/x/oauth2/google"
)

func main() {
    ctx := context.Background()
    apiKey := os.Getenv("API_KEY")
    basePath := "https://SERVICE_NAME-dot-PROJECT_NAME.appspot.com" // changed for privacy

    creds, _ := google.FindDefaultCredentials(ctx)
    jwt, _ := google.JWTConfigFromJSON(creds.JSON, basePath)

    client := jwt.Client(ctx)
    res, _ := client.Get(fmt.Sprintf("%s/REQUEST_PATH?key=%s", basePath, apiKey)) // changed for privacy

    body, _ := ioutil.ReadAll(res.Body)
    log.Printf("### http status: %d %s", res.StatusCode, res.Status)
    log.Printf("### http body: %s", body)
}

为简洁起见,我删除了此代码粘贴的错误检查,运行此代码时没有错误。结果是:

2017/10/16 07:32:38 ### http status: 401 401 Unauthorized
2017/10/16 07:32:38 ### http body: {
 "code": 16,
 "message": "JWT validation failed: Missing or invalid credentials",
 "details": [
  {
   "@type": "type.googleapis.com/google.rpc.DebugInfo",
   "stackEntries": [],
   "detail": "auth"
  }
 ]
}

在检查正在发生的事情的内部时,例如调用 jwt.TokenSource(ctx).Token(),我看到 Google 正在返回一个 id_token,但是没有 access_token(通过向 jwt 包添加一些调试日志发现):

2017/10/16 07:38:47 ### oauth2/jwt -> tokenURL: https://accounts.google.com/o/oauth2/token, form: url.Values{"grant_type":[]string{"urn:ietf:params:oauth:grant-type:jwt-bearer"}, "assertion":[]string{"...cut..."}}
2017/10/16 07:38:47 ### oauth2/jwt <- response: {
  "id_token" : "...cut..."
}
2017/10/16 07:38:47 ### oauth2/jwt <- token: &oauth2.Token{AccessToken:"", TokenType:"", RefreshToken:"", Expiry:time.Time{wall:0x0, ext:63643740079, loc:(*time.Location)(0x1424160)}, raw:map[string]interface {}{"id_token":"...cut..."}}

因此,当 oauth2 HTTP 传输尝试添加 auth header 时——它与上面的 AccessToken 字段相关联——它会生成类似 Authorization: Bearer 的字符串,因此结果失败。

我觉得我在这里遗漏了一个步骤,这对我来说在文档中并不明显。

感谢您的宝贵时间。

最佳答案

oauth 客户端应该返回 id_token 而不是 access_token。您使用的是 JWTConfigFromJSON,而不是 ConfigFromJSON,这是正确的。我认为 JWTConfigFromJSON 的第二个参数不正确,您应该改为指定范围。在这种情况下,请尝试使用 "email" 而不是 basePath

关于go - 端点 Google ID JWT 和 Golang oauth2 : have id_token, 需要 access_token?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46765300/

相关文章:

ruby-on-rails - 向我的 oauth 提供商发出发布请求时出现 invalid_grant 错误

google-cloud-platform - Google Cloud - 端点延迟监控

json - 在使用 Gorilla 的 Go ReST 服务中操作 JSON

go - 是否可以使 net.http.ServeMux 匹配整个子树?

go - 如何在无服务器 lambda 数据源中捕获 AWS AppSync 事件

带有 OAuth2 的 Spring 微服务- ResourceServer 仅返回 String 作为主体而不是我的自定义用户

javascript - 使用来自客户端 JS 代码的 OAuth 授权代码流 token 是否安全?

java - 如何在 Objectify 上返回自定义对象列表

javascript - 离线测试经过身份验证的 Cloud Endpoints 方法

json - 我如何解码 JSON?