未经授权的WebHook回调频道

时间:2015-12-11 22:06:42

标签: google-app-engine google-api google-cloud-storage

自昨天以来,我一直在努力解决这个问题。寻找帮助其他遇到类似问题的人的解决方案,但没有什么对我有用。如果有人可以帮助我,我将不胜感激!

我创建了一个项目(名称:xxx),其中app引擎(id:app-xxx)监视GCS存储桶(名称:bucket-xxx)。 App引擎和存储桶位于同一个项目中。我尝试按照列出here列出的步骤:

  1. 使用p12密钥创建服务帐户(电子邮件:xxx@app-xxx.iam.gserviceaccount.com)。

  2. 列入白名单的网址(属性:https://app-xxx.appspot.com)。我看到网站管理员搜索控制台中列出的网址。当我使用网站管理员列表API时,也列出了相同的内容。

  3. 注册域名(app-xxx.appspot.com /)

  4. 配置gsutil以使用服务帐户 " gcloud auth activate-service-account xxx@app-xxx.iam.gserviceaccount.com --key-file path / to / key.p12"。已通过" gcloud auth list"验证命令,报告:

  5. Credentialed帐户:   - xxx@app-xxx.iam.gserviceaccount.com(有效)

    1. 让应用引擎完全访问GCS存储桶 " gsutil acl ch -u app-xxx@appspot.gserviceaccount.com:FC gs:// bucket-xxx"
    2. 我在开发者控制台的“权限”页面中看到了权限: app-xxx@appspot.gserviceaccount.com(App Engine服务帐户)

      我也可以成功将文件从本地机器上传到GCS bucket-xxx: " gsutils cp local-file gs:// bucket-xxx /"

      但是,当我设置通知时,它会报告: " ServiceException:401未经授权的WebHook回调频道:https://app-xxx.appspot.com/notification"

      收到的响应标头显示以下错误: " WWW-Authenticate:Bearer realm =" https://accounts.google.com/" ;, error = invalid_token"

      任何想法在这里可能是错的?谢谢!

2 个答案:

答案 0 :(得分:4)

当您使用不是应用程序的默认服务帐户凭据(即您自己创建的服务帐户,即非自己创建的服务帐户)为App Engine应用程序指定webhook时,可能会出现问题app-xxx@appspot.gserviceaccount.com)。由于无法获得此帐户的p12密钥,因此您无法使用gsutil添加手表。

您需要做的是使用JSON API和应用程序的默认服务帐户凭据(AppAssertionCredentials)从App Engine应用程序内部添加监视。这是一个不完整的Python示例(我的默认设置,因为我不知道您的应用使用哪种语言),这说明了如何使用google-api-python-client来实现这一点:

from oauth2client.appengine import AppAssertionCredentials
from httplib2 import Http
from apiclient.discovery import build

credentials = AppAssertionCredentials('https://www.googleapis.com/auth/devstorage.read_only')
http_auth = credentials.authorize(Http())
storage = build('storage', 'v1', http=http_auth)

request = service.objects().watchAll(bucket='mybucket', body={args...})
request.execute()

请参阅watchAll的pydoc。请注意,您需要将应用程序的默认服务帐户添加到存储桶的ACL中才能使其正常工作(这几乎总是app-id@appspot.gserviceaccount.com,可在&#中查看39; Developer Console的权限部分)。

答案 1 :(得分:0)

只需扩展Sevle的答案:即使从(例如)Secret Manager 中检索默认应用程序服务帐户的凭据,然后从中创建客户端,也会发生这种情况< / em>。

在用TypeScript编写的Firebase项目中,我必须将代码从以下位置更改:

return google.auth.getClient({
    credentials,
    scopes: ['https://www.googleapis.com/auth/calendar'],
})
.then((client) => {
    client.subject = settings.get('apiUser');
    return google.calendar({
        version: 'v3',
        auth:    client,
    });
});

改为这样工作:

return new GoogleAuth({
    scopes:        ['https://www.googleapis.com/auth/calendar'],
    clientOptions: { subject: settings.get('apiUser') },
}).getClient()
    .then((client) =>
        google.calendar({
            version: 'v3',
            auth:    client,
        })
    );

请注意,第一个示例中的google中的google.auth.getClient与npm上的软件包googleapis捆绑在一起,但是第二个示例中使用的new GoogleAuth实际上来自{ {1}}。

我们对应用程序架构进行了少许更改,因此在不同的请求上我们不需要使用不同的服务帐户,因此现在对我们有用。