2

我正在尝试在第二个类似的应用程序引擎应用程序中执行由我编写的使用端点的一个应用程序引擎应用程序(python)提供的功能。

我目前使用带有 oauth2 的端点在 apppot 上运行两个应用引擎应用程序。我有一个使用端点的工作 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 参数添加到凭据中,仍然无效。我查看了其他看到此错误并尝试弄乱时钟的人,尽管这是服务器到服务器的调用,所以我认为这不是问题。我已将呼叫者的服务帐户电子邮件地址添加到被呼叫者应用的权限中。

我没有找到关于使用服务帐户调用自定义 Endpoints API 的示例应用程序或帖子,仅调用 Youtube 或 Plus 等 Google API,其中大多数都有注册调用应用程序引擎应用程序的方法。

有没有人能够使用 oauth2 在一个应用程序引擎应用程序和另一个应用程序引擎应用程序上调用端点 api 函数?

在此先感谢,-垫

4

1 回答 1

4

我已经能够在您所描述的应用程序到应用程序场景中使用服务帐户来完成这项工作。自从我接触这段代码以来已经有一段时间了,但是快速将您的代码与我的代码进行比较,我看到的两个不同之处是:

范围:

我正在参加课程https://www.googleapis.com/auth/userinfo.email的范围SignedJwtAssertionCredentials。鉴于您看到的错误消息,这可能是原因。根据此文档,我认为至少需要电子邮件范围。

我正在调用的 Endpoints 服务也指定allowed_client_ids限制对已知客户端列表的访问,其中之一是我为与这些端点对话而配置的服务帐户。

发现服务网址:

我将 discoverServiceUrl 参数传递给build()函数。鉴于您的错误消息,这似乎不太可能,但我想我会提到它。

- - 编辑 - -

根据以下请求添加示例代码。

对于 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):
    ...

希望这可以帮助。

于 2014-02-14T23:57:49.197 回答