我在端点后面有一个应用程序引擎应用程序,但我无法遵循有关添加身份验证的文档。我的偏好是允许项目中的服务帐户通过,然后执行更精细的应用程序端授权。
在我的情况下,大多数客户将在GCP之外并且将是自动程序而不是人,所以我使用JSON密钥文件认为这是要走的路(如果我错了请纠正我)。我也不想重新部署应用程序以更改用户配置,因此我按照此处的文档中的“GOOGLE ID JWT”信息进行操作:
https://cloud.google.com/endpoints/docs/openapi/service-to-service-auth
这是我招摇的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标头(与上面的AccessToken字段绑定)时,会产生类似Authorization: Bearer
的字符串,从而导致结果失败。
我觉得我在这里错过了一个步骤,这在文档中并不明显。
感谢您的时间。
答案 0 :(得分:1)
oauth客户端应该返回Iterator<String> itr = s.iterator();
while(itr.hasNext()){
Permission p = itr.next();
}
而不是id_token
。您使用的是access_token
,而不是JWTConfigFromJSON
,这是正确的。我认为ConfigFromJSON
的第二个参数是不正确的,您应该指定范围。在这种情况下,请尝试JWTConfigFromJSON
而不是"email"
。