Firebase-tools: Firebase Cloud Functions:app/invalid-credential 无法获取有效的 Google OAuth2 访问令牌 Firebase Admin SDK

创建于 2019-10-09  ·  38评论  ·  资料来源: firebase/firebase-tools

[必需] 环境信息


火力基地工具: 7.5.0


平台: macOS

[必需] 测试用例

[必需] 重现步骤

我是 Cloud Functions 的新手。 我遵循了文档和 firebase-admin 的新初始化语法,但是在服务器和本地主机上运行该函数时出现身份验证错误。

https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase -admin

@firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

我尝试用serviceAccountKey实例化 sdk,同样的问题。 https://firebase.google.com/docs/admin/setup#initialize_the_sdk

该函数在本地主机和服务器上被触发,一旦在gettingUser()调用数据库,就会抛出错误

构建后在本地运行时:

$ firebase experimental:functions:shell
firebase > const data = {some_article...}
firebase > addingNewArticle(data)
'Successfully invoked function.'
firebase > >  New article created articleId1

DEBUG: @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

/index.ts

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp();

export const addingNewArticle = functions.database
.ref('/articles/{articleId}')
.onCreate(async (snapshot, context) => {
  const articleId = context.params.articleId

  const result = await gettingUser();
  console.log(`From onCreate ${result}`);


  console.log(`New article created ${articleId}`)

  const articleVal = snapshot.val()
  const name = articleVal.name
  const addedById = articleVal.addedById

  console.log(`${name} was added by: ${addedById}`);
  console.log(`burgersVal: ${articleVal}`);
  console.log(`snapshot: ${snapshot}`);


  return Promise.all([])
})


export async function gettingUser() {
    const result = await admin.database().ref(`users/fnkjasdfadsfna.d`).once('value');
    console.log(`Looging new user ${result.val()}`);
    return result.val()
}
functions functions

最有用的评论

对于遇到此问题的任何人:

  • 如果您在模拟器中看到它,您可以通过将GOOGLE_APPLICATION_CREDENTIALS设置为服务帐户或在您的机器上运行gcloud auth application-default login来修复它。
  • 如果您在生产中看到这种情况,请立即联系 Firebase 支持,这绝不会发生。

所有38条评论

这个问题似乎没有遵循问题模板。 确保您提供所有必需的信息。

@talezion感谢您提交此文件! 只是要清楚您是希望admin.database()调用使用生产数据库还是尝试使用数据库模拟器?

@samtstern ,正确,我正在尝试从模拟器访问生产数据库。 实际上,在服务器上运行它时我也遇到了类似的身份验证错误。

这是我在服务器上得到的错误:

[2019-09-26T22:14:53.387Z]  @firebase/database: FIREBASE WARNING: Provided authentication credentials for the app named "[DEFAULT]" are invalid. This usually indicates your app was not initialized correctly. Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project. 

@talezion嗯,所以你在部署的云函数中也看到了这一点? 除了admin.initializeApp();之外,你还在任何地方初始化吗? 那应该使用应用程序默认凭据。

好的,所以我做了一个简单的函数来显示我的凭据:

const app = admin.initializeApp();

exports.helloWorld = functions.https.onRequest((request, response) => {
 response.json(app.options);
});

当我在本地调用它时,我得到如下信息:

{
    "credential": {
        "credential_": {
            "httpClient": {
                "retry": {
                    "backOffFactor": 0.5,
                    "ioErrorCodes": [
                        "ECONNRESET",
                        "ETIMEDOUT"
                    ],
                    "maxDelayInMillis": 60000,
                    "maxRetries": 4,
                    "statusCodes": [
                        503
                    ]
                }
            },
            "refreshToken": {
                "clientId": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com",
                "clientSecret": "REDACTED",
                "refreshToken": "REDACTED",
                "type": "authorized_user"
            }
        }
    },
    "databaseURL": "https://fir-dumpster.firebaseio.com",
    "projectId": "fir-dumpster",
    "storageBucket": "fir-dumpster.appspot.com"
}

@talezion你能做同样的事情并向我展示输出吗? 确保像我一样隐藏您的 clientSecret 和 refreshToken ,分享这些很危险。

@samtstern我只将它初始化为admin.initializeApp(); 。 我还尝试了https://firebase.google.com/docs/admin/setup#initialize_the_sdk 中描述的不同方法,或者使用serviceAccountKey.json没有运气。

谢谢你的例子。 请看下面的输出:

firebase > helloWorld()
Sent request to function.
firebase > 
RESPONSE RECEIVED FROM FUNCTION: 200, {
  "databaseURL": "https://<PROJECT-ID>.firebaseio.com",
  "storageBucket": "<PROJECT-ID>.appspot.com",
  "projectId": "<PROJECT-ID>",
  "credential": {
    "credential_": {
      "httpClient": {
        "retry": {
          "maxRetries": 4,
          "statusCodes": [
            503
          ],
          "ioErrorCodes": [
            "ECONNRESET",
            "ETIMEDOUT"
          ],
          "backOffFactor": 0.5,
          "maxDelayInMillis": 60000
        }
      }
    }
  }
}

@talezion确定两件事;

1) 字面意思是<PROJECT-ID>还是您的编辑?
2)嗯,很奇怪,它没有refreshToken ......我必须找出这是怎么可能的。

@samtstern

  1. 不,我只是用正确的项目 ID 替换了<PROJECT-ID>
  2. 谢谢!

好的,所以我认为在生产中响应是正常的,但在本地我期望更多。

现在有两件事:
1) 你有GOOGLE_APPLICATION_CREDENTIALS环境变量集吗?
2)你能不能再次尝试运行firebase logoutfirebase login看看这是否使它在本地工作得更好?

@samtstern

  1. 是的,我尝试设置:
    set GOOGLE_APPLICATION_CREDENTIALS="/functions/src/serviceAccountKey.json"
    然后运行shell
  2. 是的,尝试注销,然后重新登录,仍然是同样的问题

@talezion嗯好的谢谢你的确认。 说实话,我现在完全被难住了,但会继续思考这个问题。

谢谢@samtstern ,我尝试在一个全新的项目上对其进行测试,并且可以正常工作。

  1. 创建了一个新项目
  2. 初始化函数
  3. 执行相同的代码

它工作正常。

除了创建一个新项目,我删除并启动了一个新的功能项目,并部署了相同的代码。 这是我得到的错误:

@firebase/database: FIREBASE WARNING: Provided authentication credentials for the app named "[DEFAULT]" are invalid. This usually indicates your app was not initialized correctly. Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project. 

老项目是今年1月份创建的,控制台有什么需要做的吗?

我也有同样的问题。 这是我的线索:
1.- 启动一个项目和功能,一切正常。
2.-发送到GitHub并在其他计算机上打开,进行NPM安装,仍然可以正常工作。 我整晚都在这台电脑上工作,我做了一个 PUSH 但仍然可以正常工作。
3.- 回到第一台电脑make pull,然后死机。
4.- 在第二台电脑上测试,仍然可以正常工作。

如您所见,我在两台计算机上有相同的代码,其中一台在发出拉取请求后崩溃。

控制台消息说是凭证问题,我试过这个没有成功:

  • 在终端中重置我的 firebase 登录
  • 擦除本地文件中的数据库规则配置
  • 我使用功能凭据,我将它们更改为配置项目
  • 在 node_modules 文件夹项目中安装 firebase-tools

我将用空项目重新启动。

升级到 Mac OS Catalina 后,我遇到了这个问题。 为我解决的是运行以下命令:

  • firebase login
  • export GOOGLE_APPLICATION_CREDENTIALS="<PATH_TO_YOUR_SERVICE_ACCOUNT_KEY_JSON>"

有没有在某处发布的解决方案? 我今天在尝试通过本地运行的云功能访问数据库时收到此警告。

我有完全相同的问题,因为我的生活无法弄清楚发生了什么。 我尝试了多个服务帐户 jsons,多次重置我的项目,重新启动,登录和注销,重新设置GOOGLE_APPLICATION_CREDENTIALS变量,甚至切换了操作系统。
我认为这可能是我的 Windows 机器的问题,因为从那里我什至无法启动模拟器,因为它说它缺少刷新令牌,
Error: Failed to parse refresh token file: Error: Refresh token must contain a "client_secret" property.

所以我全新安装了 Linux 并设置了项目。 设置服务帐户后第一次运行正常,但是在重新启动 linux 机器后,我再次遇到完全相同的问题。
Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND".

这是我从云功能中选择的选项:

{
    "credential": {
        "credential_": {
            "httpClient": {
                "retry": {
                    "maxRetries": 4,
                    "statusCodes": [
                        503
                    ],
                    "ioErrorCodes": [
                        "ECONNRESET",
                        "ETIMEDOUT"
                    ],
                    "backOffFactor": 0.5,
                    "maxDelayInMillis": 60000
                }
            }
        }
    },
    "databaseURL": "https://REDACTED.firebaseio.com"
}

初始化为:

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: 'https://REDACTED.firebaseio.com'
});

同样的问题在这里! 在我的 linux 桌面上工作正常。 无限部署在 EKS(高山)输出上:

[2019-12-20T20:28:27.137Z]@firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"通过\"credential 提供给 initializeApp() 的凭据实现\"属性无法获取有效的 Google OAuth2 访问令牌,并出现以下错误:\"获取访问令牌时出错:invalid_grant(无效的颁发者:不是服务帐户。)\”。可能有两个原因:(1) 您的服务器时间未正确同步或 (2) 您的证书密钥文件已被吊销。要解决 (1),请重新同步服务器上的时间。要解决 (2),请确保您的密钥文件的密钥 ID 仍然存在https://console.firebase.google.com/iam-admin/serviceaccounts/project。如果没有,请在https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk生成新的密钥文件

新密钥已生成并在本地工作得很好,但在部署在云上时又不行。

请问有人解决了吗?

和我一样
[2019-12-21T11:21:35.790Z] @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Error fetching access token: <html>\r\n<head><title>302 Found</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>302 Found</h1></center>\r\n<hr><center>nginx/1.14.2</center>\r\n</body>\r\n</html>\r\n\"."}

和作者一样的问题:

我已按照此参考来初始化我的应用程序:

admin.initializeApp({ credential: admin.credential.applicationDefault(), ... })

(实际上完全省略credential具有完全相同的结果),并且在本地机器(不在云中)上运行时失败并出现以下错误:

错误:通过“凭据”属性提供给 initializeApp() 的凭据实现无法获取有效的 Google OAuth2 访问令牌,并出现以下错误:“获取访问令牌时出错:发出请求时出错:getaddrinfo ENOTFOUND metadata.google.internal。错误代码:发现”

(有趣的是,这个问题与firebase-admin ,但这是 Google 上的第一次成功,所以我想我会加入派对......)

metadata.google.internal?

这是最奇怪的部分:它试图从某个metadata.google.internal域中获取令牌,这听起来似乎只能在 Google Cloud Function 中使用? 不再支持本地开发了吗?

无论哪种方式; 我调试了一下,发现它发生在node_modules/firebase-admin/lib/auth/credential.js

它有一个大脂肪:

var GOOGLE_METADATA_SERVICE_HOST = 'metadata.google.internal';

这里是源码链接

@samtstern有更新吗? 为什么它试图从每个人的内部地址获取代币?

我在未登录且未使用GOOGLE_APPLICATION_CREDENTIALS也看到了这一点。 我看到它在运行firebase functions:shell然后为实时数据库调用onWrite数据库触发器时发生。 触发器只返回 null 并且不执行任何其他操作。

>  [2020-01-17T20:00:30.997Z]  @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND\"."}

同样的问题在这里,仍然没有解决。

同样的问题

错误消息很神秘,但修复(至少在我的情况下)很简单。 正如@hiranya911在此相关问题中指出的那样,如果您的配置/环境变量设置不正确,则会发生错误,您想特别仔细检查您的GOOGLE_APPLICATION_CREDENTIALS

对于遇到此问题的任何人:

  • 如果您在模拟器中看到它,您可以通过将GOOGLE_APPLICATION_CREDENTIALS设置为服务帐户或在您的机器上运行gcloud auth application-default login来修复它。
  • 如果您在生产中看到这种情况,请立即联系 Firebase 支持,这绝不会发生。

对于遇到此问题的任何人:

  • 如果您在模拟器中看到它,您可以通过将GOOGLE_APPLICATION_CREDENTIALS设置为服务帐户或在您的机器上运行gcloud auth application-default login来修复它。
  • 如果您在生产中看到这种情况,请立即联系 Firebase 支持,这绝不会发生。

同样的问题,但用@samtstern的解决方案修复了!! 谢谢你。

谢谢@samtstern。 由于多个 Google 帐户,我遇到了这个问题。 一个在 Firebase CLI 上使用,另一个登录到 Google Cloud CLI……使用相同的帐户重新登录两者解决了问题。
🙌

可以确认@samtstern设置GOOGLE_APPLICATION_CREDENTIALS的解决方案对我有用

我在将函数模拟器与我的实时数据库(真正的在线数据库,如果可能的话,不模拟)一起使用时遇到了问题。

[2020-03-15T23:36:45.803Z]  @firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal metadata.google.internal:80. Error code: ENOTFOUND\"."}

我试过将变量export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json"
https://cloud.google.com/docs/authentication/getting-started
尝试指出defaultAccount.jsonserviceAccount.json

我可能做错了什么?

我也遇到了麻烦(同样的Error code: ENOTFOUND\"."错误)......即使使用samtstern 的解决方案......所以,我结合了两个解决方案; 一方面是从谷歌云控制台生成 json.key ,另一方面是从这个 StackOverflow 答案中生成

第一部分(谷歌云控制台):

  • 通过单击屏幕顶部的“选择项目”按钮选择所需的项目
  • 通过转到“名称”下显示“App Engine 默认服务帐户”行中的“三个点”菜单来创建一个密钥
  • 这将下载__your_app_sth__.json密钥文件

第二部分(SO答案):

  • 转到您的函数所在的index.json ,并在admin.initializeApp()处将生成的.json文件中的数据放入 StackOveflow 答案中的格式。

干杯!

这是我设法解决问题的方法:

错误信息:

错误:通过“凭据”属性提供给 initializeApp() 的凭据实现无法获取有效的 Google OAuth2 访问令牌,并出现以下错误:“获取访问令牌时出错:invalid_grant(错误请求)”。 有两个可能的原因:(1) 您的服务器时间未正确同步或 (2) 您的证书密钥文件已被吊销。 要解决(1),请重新同步服务器上的时间。 要解决 (2),请确保您的密钥文件的密钥 ID 仍然存在于https://console.firebase.google.com/iam-admin/serviceaccounts/project。 如果没有,请在https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk生成一个新的密钥文件

解决方案

步骤 1:将本地 pc 的时间与时间服务器同步。 在我的情况下有 1 秒的差异,但 Windows 10 有一个 SYNC NOW 按钮,使用它并同步时间。 检查它: https :

第 2 步:转到上面的链接https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk 。 在那里生成私钥。 将其保存到 PC 上的文件夹中。 说“D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json”。 然后在你的函数文件夹的 index.ts 文件中,更新如下代码:

`
从'firebase-functions'导入*作为函数;
从“firebase-admin”导入 * 作为管理员;

var serviceAccount = require("D://Path//project-101-firebase-adminsdk-cb748-fhry6shja.json");
admin.initializeApp({
凭据:admin.credential.cert(serviceAccount),
数据库网址:“https://project-101.firebaseio.com”
});
`

可选步骤:(我不确定这是否仍然需要) - 我们可以在电脑上设置 GOOGLE_APPLICATION_CREDENTIALS 如下:

set GOOGLE_APPLICATION_CREDENTIALS="D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json"

测试它是否正确使用 - 设置 GOOGLE_APPLICATION_CREDENTIALS


最后为了在模拟器上测试运行云功能,我遵循了这篇写得很好的文章:
https://medium.com/@moki298/test -your-firebase-cloud-functions-locally-using-cloud-functions-shell-32c821f8a5ce

基本上 -

  1. 在管理员模式下打开 CMD,然后导航到您的功能文件夹。
  2. 为您的函数 ts 文件运行 transpile 命令。 每次我们更改代码时都需要这样做。

npm run-script build

  1. 使用命令输入 firebase 函数 shell:

firebase functions:shell

  1. 运行您的函数并查看它是否运行良好(希望如此!)。 假设该函数是名称为 TestFunc 的 http 云函数 - 所以在函数外壳类型中:

TestFunc()

那应该这样做。

转到上面的链接https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk 。 在那里生成私钥。 将其保存到 PC 上的文件夹中。 说“D:\Path\project-101-firebase-adminsdk-cb748-fhry6shja.json”。 然后在你的函数文件夹的 index.ts 文件中,更新如下代码:

`
从'firebase-functions'导入*作为函数;
从“firebase-admin”导入 * 作为管理员;

var serviceAccount = require("D://Path//project-101-firebase-adminsdk-cb748-fhry6shja.json");
admin.initializeApp({
凭据:admin.credential.cert(serviceAccount),
数据库网址:“https://project-101.firebaseio.com”
});
`

@pranaykothari你太棒了🤘🏻!

对于看到此内容的任何人,只需将下载的 json 放在您的 repo 的/functions目录中,然后像这样导入
const credential = require("./credentails.json")
您可以将 json 重命名为“credentails.json”之类的名称,以便更容易理解您的文件。

⚠️ 警告:你不应该提交这种类型的文件。 它非常敏感。 通过在您的functions/.gitignore添加其名称来将其从提交中排除。

我完成了

gcloud auth application-default login
您的浏览器已打开访问:

它工作但得到

users.js:60 Error listing users: Error: //cloud.google.com/docs/authentication/. Raw server response: "{"error":{"code":403,"message":"Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.","errors":[{"message":"Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the identitytoolkit.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.","domain":"usageLimits","reason":"accessNotConfigured","extendedHelp":"https://console.developers.google.com"}],"status":"PERMISSION_DENIED"}}"

我也试过这个:

下载管理文件并像这样在 bash 中导出:
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/svelte-fullstack-starter-firebase-adminsdk-4bq35-xxxx.json"

但是在运行模拟器时,我遇到了与上面相同的问题
image

@quantuminformation当您执行gcloud auth application-default login您将获得用户凭据( firebase logini是同一种凭据)。 某些 API,例如支持 Firebase 身份验证的identitytoolkit API,不接受这些凭据。

如果您想使用这些 API,您应该使用服务帐户进行身份验证。 将GOOGLE_APPLICATION_CREDENTIALS环境变量设置为指向服务帐户私钥 JSON 文件:
https://cloud.google.com/docs/authentication/getting-started#setting_the_environment_variable


编辑我看到你已经这样做了。 如果您正在使用 env var 并且模拟器不尊重您的凭据,您应该提交一个新问题。

我升级到
8.4.3并且运行良好

苹果系统

[必需] 测试用例

函数代码: https :

[必需] 重现步骤

  • 在上面的目录中运行gcloud auth application-default login

创建文件Credentials saved to file: [/Users/nikos/.config/gcloud/application_default_credentials.json]
不错的新触感)

  • 然后我删除我现有的
    环境变量 [GOOGLE_APPLICATION_CREDENTIALS] 设置为:
    [/用户/nikos/svelte-fullstack-starter-firebase-adminsdk-4bq35-f77b2
    b4fc4.json]

这是创建的:
image

  • 最后我运行firebase emulators:start --only functions --inspect-functions

image

当我运行指向本地仿真的应用程序时
base = "http://localhost:5002/svelte-fullstack-starter/us-central1"

使用我的实时数据调试工作正常!

就我而言,将本地电脑/笔记本电脑上的时间与时间服务器同步解决了问题,谢谢! @pranaykothari

嘿大家。 CLI 的8.5.0版本包括此更改:
https://github.com/firebase/firebase-tools/pull/2214

有了这个改变,你应该不再需要运行gcloud auth application-default login来使用模拟器(尽管你可以,如果你愿意的话)。 只要您使用firebase login登录,我们就会将您的用户凭据传递到 Functions 模拟器中。

所以我相信这个问题现在应该得到解决。 如果您有进一步的意外身份验证行为,请提交一个新问题并提及我!

您是否需要在您的项目中生成 SDK 管理 Firebase。

访问“设置”>“服务帐户”并生成 SDK 管理 Firebase

此页面是否有帮助?
0 / 5 - 0 等级