我在端点后面有一个 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/