如何对 Google Cloud Endpoint 进行经过身份验证的调用?
How to make an authenticated call to Google Cloud Endpoint?
我已经设置了一个简单的标准环境 Google App Engine 项目,它通过执行此处教程中的步骤使用 Cloud Endpoints:
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 未经授权的 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 应用程序使用正确版本的云端点配置。
- 端点配置中的客户端 ID (x-google-audiences) 与
javascript 网络应用正在发布的客户端 ID。
关于如何解决这个问题有什么想法吗?
使用示例代码在以下位置设置终点:
https://cloud.google.com/endpoints/docs/frameworks/python/create_api
和
https://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
我已经设置了一个简单的标准环境 Google App Engine 项目,它通过执行此处教程中的步骤使用 Cloud Endpoints:
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 未经授权的 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 应用程序使用正确版本的云端点配置。
- 端点配置中的客户端 ID (x-google-audiences) 与 javascript 网络应用正在发布的客户端 ID。
关于如何解决这个问题有什么想法吗?
使用示例代码在以下位置设置终点: https://cloud.google.com/endpoints/docs/frameworks/python/create_api 和 https://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