【问题标题】:How to make an authenticated call to Google Cloud Endpoint?如何对 Google Cloud Endpoint 进行经过身份验证的调用?
【发布时间】:2019-06-01 15:58:30
【问题描述】:

我通过此处教程中的步骤设置了一个使用 Cloud Endpoints 的简单、标准环境的 Google App Engine 项目:

https://cloud.google.com/endpoints/docs/frameworks/python/get-started-frameworks-python

这很好用——我可以对 echo 端点进行 curl 调用并获得预期的结果。

但是,我无法成功调用经过身份验证的端点。 我正在按照此处的步骤操作:https://cloud.google.com/endpoints/docs/frameworks/python/javascript-client,虽然我可以成功登录,但当我发送经过身份验证的示例请求时,我会收到 401 Unauthorized HTTP 响应。

从我看到的服务器日志中:

Client ID is not allowed: <my client id>.apps.googleusercontent.com (/base/data/home/apps/m~bfg-data-analytics/20190106t144214.415219868228932029/lib/endpoints/users_id_token.py:508)

到目前为止,我已经检查过:

  • Web 应用正在使用正确版本的云端点配置。
  • 端点配置 (x-google-audiences) 中的客户端 ID 与 javascript Web 应用发布的客户端 ID。

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 您的应用源代码中的客户端 ID 是否也正确?使用框架,权威的是源代码,而不是生成的 OpenAPI 配置。
  • 很高兴知道谢谢 - 不幸的是,它也在这里匹配。
  • 请在您的 api 和方法上显示装饰器,以及您正在调用的方法的代码。你可以省略你的业务逻辑;我只需要查看与身份验证有关的代码部分。
  • 我只是按照教程进行操作 - 我还没有添加我的业务逻辑。但是,我得到了它的工作(见下文)!感谢您关注我。

标签: authentication google-cloud-platform google-cloud-endpoints restful-authentication


【解决方案1】:

使用示例代码设置端点: https://cloud.google.com/endpoints/docs/frameworks/python/create_apihttps://cloud.google.com/endpoints/docs/frameworks/python/service-account-authentication

并修改用于从以下位置生成令牌的 python 代码: https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_google_id_token

我已经搞定了。

这是服务器端点代码:

import endpoints
from endpoints import message_types
from endpoints import messages
from endpoints import remote

class EchoRequest(messages.Message):
    message = messages.StringField(1)

class EchoResponse(messages.Message):
    """A proto Message that contains a simple string field."""
    message = messages.StringField(1)


ECHO_RESOURCE = endpoints.ResourceContainer(
    EchoRequest,
    n=messages.IntegerField(2, default=1))

@endpoints.api(
    name='echo',
    version='v1',
    issuers={'serviceAccount': endpoints.Issuer(
    'MY-PROJECT@appspot.gserviceaccount.com',
    'https://www.googleapis.com/robot/v1/metadata/x509/MY-PROJECT@appspot.gserviceaccount.com')},
    audiences={'serviceAccount': ['MY-PROJECT@appspot.gserviceaccount.com']})

class EchoApi(remote.Service):
    # Authenticated POST API
    # curl -H "Authorization: Bearer $token --request POST --header "Content-Type: applicationjson" --data '{"message":"echo"}' https://MY-PROJECT@appspot.com/_ah/api/echo/v1/echo?n=5
    @endpoints.method(
        # This method takes a ResourceContainer defined above.
        ECHO_RESOURCE,
        # This method returns an Echo message.
        EchoResponse,
        path='echo',
        http_method='POST',
        name='echo')
    def echo(self, request):
        print "getting current user"
        user = endpoints.get_current_user()
        print user
        # if user == none return 401 unauthorized
        if not user:
            raise endpoints.UnauthorizedException

        # Create an output message including the user's email
        output_message = ' '.join([request.message] * request.n) + ' ' + user.email()
        return EchoResponse(message=output_message)

api = endpoints.api_server([EchoApi])

以及生成有效令牌的代码

    import base64
    import json
    import time
    import google

    import google.auth
    from google.auth import jwt

    def generate_token(audience, json_keyfile, client_id, service_account_email):
        signer = google.auth.crypt.RSASigner.from_service_account_file(json_keyfile)

        now = int(time.time())
        expires = now + 3600  # One hour in seconds

        payload = {
            'iat': now,
            'exp': expires,
            'aud' : audience,
            'iss': service_account_email,
            'sub': client_id,
            'email' : service_account_email
        }

        jwt = google.auth.jwt.encode(signer, payload)

        return jwt

token = generate_token(
    audience="MY-PROJECT@appspot.gserviceaccount.com",              # must match x-google-audiences
    json_keyfile="./key-file-for-service-account.json",
    client_id="xxxxxxxxxxxxxxxxxxxxx",                              # client_id from key file
    service_account_email="MY-PROJECT@appspot.gserviceaccount.com")

print token

使用 curl 进行经过身份验证的调用

export token=`python main.py` 
curl -H "Authorization: Bearer $token" --request POST --header "Content-Type: application/json" --data '{"message":"secure"}' https://MY-PROJECT.appspot.com/_ah/api/echo/v1/echo?n=5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 1970-01-01
    • 2019-11-06
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    相关资源
    最近更新 更多