【问题标题】:Unauthorized WebHook callback channel未经授权的 WebHook 回调通道
【发布时间】:2015-12-11 22:06:41
【问题描述】:

从昨天开始我一直在努力解决这个问题。寻找可以帮助其他面临类似问题的人的解决方案,但对我没有任何帮助。如果有人可以帮助我,我将不胜感激!

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

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

  2. 列入白名单的 URL(属性:https://app-xxx.appspot.com)。我看到网站管理员搜索控制台中列出的 URL。当我使用网站管理员列表 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”命令验证,报告:

认证帐户: - xxx@app-xxx.iam.gserviceaccount.com(活跃)

  1. 授予应用引擎对 GCS 存储桶的完全访问权限 "gsutil acl ch -u app-xxx@appspot.gserviceaccount.com:FC gs://bucket-xxx"

我在开发者控制台的“权限”页面中看到了权限: app-xxx@appspot.gserviceaccount.com(App Engine 服务帐号)

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

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

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

你有什么想法吗?谢谢!

【问题讨论】:

  • “当我设置通知时” - 你能提供关于你做了什么设置的详细信息,以及在哪里设置的吗?例如。您是使用 gsutil 还是通过 API 调用?
  • 我正在使用 gsutil "gsutil notification watchbucket https://app-xxx.appspot.com/notification gs://bucket-xxx"
  • 这是我使用 "gsutil -d" { "error": { "errors": [ { "domain": "global", "reason": "push.webhookUrlUnauthorized" 时得到的, "message": "未授权的 WebHook 回调通道:https://app-xxx.appspot.com/notification" } ], "code": 401, "message": "未授权的 WebHook 回调通道:https://app- xxx.appspot.com/notification" } }
  • 谁有这个工作?这是一个错误,因为我已经在多个 GAE 项目和服务帐户中尝试过;无法让它工作。

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


【解决方案1】:

当您使用不是应用程序默认服务帐户凭据的服务帐户(即您自己创建的,不是 app-xxx@ apppot.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,可在开发者控制台的“权限”部分查看)。

【讨论】:

  • 是的,正如您所指出的,我没有使用应用程序的默认服务帐户 (app-xxx@appspot.gserviceaccount.com)。在 App Engine 中构建存储服务对我有用。感谢和抱歉迟到的回复!
  • 我的问题是没有使用 app-engine 的凭证文件。
【解决方案2】:

只是为了扩展 Sevle 的回答:即使您从(例如)Secret Manager 检索默认应用程序服务帐户的凭据,也会发生这种情况然后从它们创建一个客户端。

在一个用 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.auth.getClient 中的google 与npm 上的包googleapis 捆绑在一起,但第二个示例中使用的new GoogleAuth 实际上来自google-auth-library

我们稍微改变了应用架构,因此我们不需要针对不同请求使用不同的服务帐户,所以现在这对我们有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-18
    • 2021-04-15
    • 2014-11-02
    • 2016-04-13
    • 1970-01-01
    • 2018-03-06
    • 2017-06-06
    • 2017-07-20
    相关资源
    最近更新 更多