Firebase 的签名错误 getSignedUrl()

Posted

技术标签:

【中文标题】Firebase 的签名错误 getSignedUrl()【英文标题】:SigningError with Firebase getSignedUrl() 【发布时间】:2019-04-17 17:58:26 【问题描述】:

我正在尝试使用 file.getSignedUrl() 通过 Google Cloud Functions (Nodejs) 从 Firebase Storage 获取下载 URL。我在 Cloud Functions 控制台中收到此错误:

 SigningError: A Forbidden error was returned while attempting to retrieve an access token for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have the correct permission scopes specified. Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/myapp-cd94d/serviceAccounts/myapp-cd94d@appspot.gserviceaccount.com.
    at SigningError (/user_code/node_modules/@google-cloud/storage/build/src/file.js:58:9)
    at authClient.sign.then.catch.err (/user_code/node_modules/@google-cloud/storage/build/src/file.js:1019:22)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7) name: 'SigningError' 

我从Add the Firebase Admin SDK to Your Server 文档中复制了代码。我的functions 文件夹中有我的serviceAccountKey.jsonfirebase deploy 没有给我错误

Error parsing triggers: Cannot find module 'serviceAccountKey.json'

所以我必须有正确的路径到我的serviceAccountKey.json。我什至生成了一个新的私钥,但没有解决问题。我有firebase-admin 6.1.0firebase-tools 6.1.0。这是我的代码的相关部分:

const admin = require('firebase-admin');
var serviceAccount = require("./myapp-cd94d-firebase-adminsdk-1234x-sEcReT.json");

admin.initializeApp(
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://myapp-cd94d.firebaseio.com"
);

...

const config = 
  action: 'read',
    expires: '03-17-2025'
  ;

file.getSignedUrl(config).then(function(data) 
    const url = data[0];
    console.log(url);
  )
  .catch(function(error) 
    console.error(error);
  )

我看到Doug Stevenson's answer 有不同的代码,但它似乎等同于文档中的代码。

【问题讨论】:

【参考方案1】:

答案与Cloud Identity and Access Management 有关。首先,转到您的 Google Cloud Platform IAM & admin 页面。您会看到各种服务帐户。查找类似于 myapp-cd99d@appspot.gserviceaccount.com 的服务帐户。它应该在Name 列中显示App Engine default service account。 (如果错误消息引用了不同的服务帐号,请找到该服务帐号。)

Role 列中,您可能会看到也可能不会看到一些角色。如果您收到SigningError 消息,则Role 列缺少角色服务帐户令牌创建者。选中myapp-cd99d@appspot.gserviceaccount.com 左侧的复选框以选择服务帐户,然后单击右侧的铅笔进行编辑。在下一个屏幕中,单击+ADD ANOTHER ROLE。向下滚动到Service Accounts,选择Service Account Token Creator,然后保存。现在您应该在Roles 列中看到Service Account Token Creator 对应App Engine default service account。现在您有权创建签名令牌。

接下来,重复这些步骤并为Storage Object Creator 添加一个角色。这将允许您运行getSignedURL()

您可以另选分配 Service Account Admin 和 Storage Admin,它们分别包括 Service Account Token CreatorStorage Object Creator 角色以及其他角色。

现在,如果您收到的是 SingingError 消息,那可能是因为您将布鲁斯·斯普林斯汀 (Bruce Springsteen) 的《光荣岁月》(Glory Days) 走调了。 :-)

【讨论】:

我想知道的是为什么这没有被处理/记录 “默认情况下,您从 Firebase 控制台获取的服务帐户 ID,以及通过 Cloud Functions 自动发现的服务帐户 ID 没有这些权限”来自 medium article @Thomas David Kehoe。嗨托马斯。我以 .txt 的格式在 Firebase 云存储中存储了一个文件。使用使用 Node.js 的 https api。该文件包含有关用户详细信息的一些数据。我想下载该文件以及该文件中的数据并发送到另一台服务器。我得到了该存储文件的网址。如何获取文件中的数据?你对此有什么想法吗? @ThomasDavidKehoe 如何使用 gcloud 做到这一点,我看到了这个链接 cloud.google.com/iam/docs/granting-roles-to-service-accounts 但你能给我举个例子吗? Thomas David Kehoe 的回答让我指出了正确的方向,但我找不到 Storage Object Creator 角色?我遇到了这个 SO 答案,它最终解决了为我的 firebase admin SDK 授予创建 SignedURL 所需的权限的问题:***.com/a/53422174/10541855 我还发现这篇中等文章也很有帮助medium.com/@hiranya911/…【参考方案2】:

在我的例子中,我启用了身份和访问管理 (IAM),网址如下:

https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project="你的 项目名称”

【讨论】:

这终于对我有用了。 https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project=PROJECT_NUMBER。 PROJECT_NUMBER 来自 firebase 项目设置。我的项目的 12 位数字。

以上是关于Firebase 的签名错误 getSignedUrl()的主要内容,如果未能解决你的问题,请参考以下文章

条带错误:未找到与有效负载的预期签名匹配的签名

如何在 firebase 函数中检查 Stripe webhook 签名

字段“签名”的值不正确:值为 662655099,但应为 67324752

无法将数据从 Stripe webhook 发送到 Firebase

Firebase 电话号码身份验证错误

使用 Firebase 函数获取上传到 Firebase 存储的 pdf 的签名下载 URL