错误:无法加载默认凭据(Firebase函数到Firestore)

Bur*_*loo 11 firebase google-oauth google-cloud-functions google-cloud-firestore firebase-cli

我正在尝试为Firebase Cloud Functions编写一个onCall函数,该函数在Firestore数据库上执行高级查询任务(即,根据AutoML自然lang检查文本查询以获取类别,等等),但是在尝试查询来自数据库的功能:

Error getting documents ::  Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
    at GoogleAuth.getApplicationDefaultAsync (/srv/node_modules/google-auth-library/build/src/auth/googleauth.js:161:19)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7)
Run Code Online (Sandbox Code Playgroud)

功能:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();

exports.query = functions.https.onCall((data, context) => {
    const text = data.text;
    var results = [];
    const promise = db.collection('providers').get()
    promise.then((snapshot) => {
        console.log('marker');
        snapshot.forEach((doc) => {
            results.push({id: doc.id, data: doc.data()});
        });
        console.log('yessir');
        return {results: results};
    }).catch((err) => {
        console.log('Error getting documents :: ', err)
        console.log('nosir');
        return {results: "no results"};
    });
});
Run Code Online (Sandbox Code Playgroud)

输出更长:

Function execution started
Function execution took 8ms, finished with status code: 200
Error getting documents :: (etc, same error)
nosir
Run Code Online (Sandbox Code Playgroud)

示例2(运行无变化):

Function execution started
Function execution took 1200 ms, finished with status code: 200
marker
yessir
Run Code Online (Sandbox Code Playgroud)

我不知道此问题来自何处或如何解决。有什么帮助吗?

问候。

dpe*_*net 30

我有同样的错误“无法加载默认凭据”。

使用npm update. 更准确地说firebase-adminfirebase-functions

更新前:

"dependencies": {
    "@google-cloud/firestore": "^1.3.0",
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.2.0"
}
Run Code Online (Sandbox Code Playgroud)

更新后:

"dependencies": {
    "@google-cloud/firestore": "^1.3.0",
    "firebase-admin": "^8.6.0",
    "firebase-functions": "^3.3.0"
}
Run Code Online (Sandbox Code Playgroud)

我将它添加serviceAccountKey.json到我的项目中,并使用我的 firebase 项目的服务帐户设置中提供的代码更改了导入。

从 :

var admin = require('firebase-admin')

admin.initializeApp()
Run Code Online (Sandbox Code Playgroud)

到:

var admin = require('firebase-admin');    
var serviceAccount = require('path/to/serviceAccountKey.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://my-project.firebaseio.com'
});
Run Code Online (Sandbox Code Playgroud)

请参阅下面@Fernando Rocha的回答以访问您的 firebase 项目的帐户设置。

  • 这个答案是非常糟糕的做法,因为它涉及将服务帐户密钥放入云函数源中。虽然它将使密钥可供项目使用,但付诸实践是不合适的。 (11认同)

sha*_*ill 23

@aldobaie 的回答帮助我弄清楚我的用例发生了什么。对于那些不想在所有调用中添加 async/await 的人,请记住 firestore 调用返回 promise,因此在它们之前添加return具有相同的效果。

就我而言:

function doSomething(...) {
    return admin.firestore().collection(...).doc(...).get()
        .then((doc) => {...})
        .catch(err => {...})
}

module.exports = functions.firestore.document('collection/{docId}').onWrite((change, context) => {
    return doSomething()
})
Run Code Online (Sandbox Code Playgroud)

I think the accepted answer goes against Firebase's recommend configuration. The function environment has access to admin credentials already, and passing your key in the code is not recommended.

I do it like this:

const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
Run Code Online (Sandbox Code Playgroud)

  • 这为我解决了问题——返回一个承诺解决了我的身份验证问题! (3认同)
  • 这也是我完全相同的问题。当我将一个云函数转换为 async/await 时,它开始失败,并且我忘记返回结果承诺。您可以在 firebase 日志中看到该函数成功返回,然后几秒钟后将记录身份验证问题。异步代码试图在云函数终止后执行,并且身份验证信息现在消失了。完全有道理。 (2认同)

Fer*_*cha 19

我要做的是将firebase admin sdk密钥添加到我的项目中。

我在下载

https://console.firebase.google.com/u/0/project/ YOUR_PROJECT_ID / settings / serviceaccounts / adminsdk

管理员SDK密钥下载页面

然后admin.initializeApp();我更改为:

admin.initializeApp({
    credential: admin.credential.cert(require('../keys/admin.json'))
});
Run Code Online (Sandbox Code Playgroud)

我的文件夹结构是

??? key
?   ??? admin.json
??? src
?   ??? index.ts
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个合适的答案,因为它将可撤销的服务帐户凭据嵌入到函数中。源存储库中的机密不合适,并且在服务帐户凭证轮换强制重新部署云功能的情况下部署的机密也不合适。 (4认同)
  • 我赞成的所有答案并且不做这种可怕的安全实践都是适当的,我添加答案是不合适的。 (2认同)

ald*_*aie 17

我自己也遇到了同样的问题。有时该功能可以工作,但很多时候它会通过Error: Could not load the default credentials错误。我相信通过观察回调已经解决了这个问题。在使用awaitasync前缀调用回调之前,您必须保持函数运行。

Firebase Cloud Functions 不允许在处理器终止后通过回调访问处理器!这就是我们得到Error: Could not load the default credentials错误的原因。

所以,只要你有一个.then() function前缀await和它的函数前缀,它就在它里面,async任何对函数的调用都用await.

async function registerUser(..) {
    ...
    await admin.firestore().collection(..)...
    ...
}
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助你!

  • 这很有效。对于其他偶然发现这一问题的人来说,函数代码中可能有多个承诺。每一项都需要等待,而不仅仅是主要的一项。 (3认同)

Sha*_*tin 8

另一种选择是在环境变量中设置服务帐户密钥,而不是通过调用firebaseAdmin.initializeApp({ credential }).

Linux

export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json"
Run Code Online (Sandbox Code Playgroud)

Windows PowerShell

$env:GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\[FILE_NAME].json"
Run Code Online (Sandbox Code Playgroud)

后记:更好的选择可能是使用本地模拟器套件

  • 据我记得,当我们部署到 Firebase @Sergio 时,我们不需要这些凭据。 (4认同)