我正在尝试执行一个由我编写的应用程序引擎应用程序(python)提供的功能,它使用端点,在第二个类似的应用程序引擎应用程序中。
我目前使用带有oauth2的端点在appspot上运行两个app引擎应用程序。我有一个工作的javascript客户端,它使用端点,通过授权和身份验证执行功能。所以我知道后端应用程序引擎服务器正在运行,并且是一个正确暴露的端点。我还可以使用api explorer和发现服务浏览API。
由于这是服务器到服务器的链接,我认为服务帐户是我想用于oauth2身份验证的。所以我在应用引擎控制台的客户端应用中创建了服务帐户。
以下是在调用者上运行的代码:
f = file('key2.pem', 'rb')
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials(
'my-service-account-email-from-caller-app@developer.gserviceaccount.com',
key,
scope='https://my-app-id.appspot.com/_ah/api/my-api/v1')
http = credentials.authorize(httplib2.Http())
service = build("my-api", "v1", http=http)
当我运行此代码时,出现错误:AccessTokenRefreshError:invalid_grant
我尝试了很多其他的事情,在凭证中添加了developerKey或discoveryUrl参数,仍然是无效的授权。 我看了看过这个错误的其他人,并试图弄乱时钟,虽然这是一个服务器到服务器调用,所以我不认为这是问题。 我已将呼叫者的服务帐户电子邮件地址添加到被叫方应用程序的权限。
我还没有找到一个示例应用或关于使用服务帐户来调用自定义端点API的帖子,只是为了调用Youtube或Plus等Google API,其中大多数都有注册调用应用引擎应用的方法。 / p>
是否有人能够使用oauth2在另一个app引擎应用程序上调用端点api函数?
提前致谢, -mat
答案 0 :(得分:4)
我已经能够像您所描述的那样在应用到应用场景中使用服务帐户。自从我触及这段代码以来已经有一段时间了,但是很快将你的代码与我的代码进行比较,我看到的两个不同之处是:
我正在https://www.googleapis.com/auth/userinfo.email
传递SignedJwtAssertionCredentials
类的范围。鉴于您看到的错误消息,这可能是原因。我认为根据this documentation,电子邮件范围是最低要求。
我正在呼叫的我的终端服务也指定allowed_client_ids
以限制对已知客户端列表的访问,其中一个是我配置为与这些端点通信的服务帐户。
我将discoverServiceUrl参数传递给build()
函数。鉴于您的错误消息,这似乎不太可能,但我想提到它。
---- ---- EDIT
根据以下请求添加示例代码。
对于ID = 1234567890的Google控制台项目,这是我用来调用服务端点的客户端代码:
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
service_account_email = '1234567890-aasgqg243rsaggw4@developer.gserviceaccount.com'
key_file_path = os.path.join(config.base_path, 'myservice.pem')
key_file = file(key_file_path, 'rb')
key = key_file.read()
key_file.close()
credential = SignedJwtAssertionCredentials(service_account_email, key, 'https://www.googleapis.com/auth/userinfo.email')
http = credential.authorize(httplib2.Http())
discoveryServiceUrl = 'http://mysite.appspot.com/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest'
myservice = build('myservice', 'v1', http=http, discoveryServiceUrl=discoveryServiceUrl)
这是使用allowed_client_ids
参数指定我的google api项目的服务声明(ID:1234567890)
@myservice_api.api_class(resource_name='myservice', path='myservice', allowed_client_ids=['1234567890.apps.googleusercontent.com', '1234567890-aasgqg243rsaggw4.apps.googleusercontent.com', endpoints.API_EXPLORER_CLIENT_ID])
class MyService(remote.Service):
...
希望这有帮助。