【问题标题】:Firebase Service Account Private Key won't parse on Node.js appFirebase 服务帐户私钥不会在 Node.js 应用程序上解析
【发布时间】:2021-08-06 07:39:05
【问题描述】:

我正在将 node.js 后端部署到 heroku,每次尝试部署时都会遇到此错误:

2021-05-17T00:37:50.169199+00:00 app[web.1]: > server@1.0.0 start /app
2021-05-17T00:37:50.169199+00:00 app[web.1]: > node index.js
2021-05-17T00:37:50.169200+00:00 app[web.1]: 
2021-05-17T00:37:50.367405+00:00 app[web.1]: /app/node_modules/firebase-admin/lib/credential/credential-internal.js:142
2021-05-17T00:37:50.367407+00:00 app[web.1]:             throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse private key: ' + error);
2021-05-17T00:37:50.367407+00:00 app[web.1]:             ^
2021-05-17T00:37:50.367407+00:00 app[web.1]: 
2021-05-17T00:37:50.367408+00:00 app[web.1]: FirebaseAppError: Failed to parse private key: Error: Invalid PEM formatted message.
2021-05-17T00:37:50.367408+00:00 app[web.1]:     at FirebaseAppError.FirebaseError [as constructor] (/app/node_modules/firebase-admin/lib/utils/error.js:44:28)
2021-05-17T00:37:50.367408+00:00 app[web.1]:     at FirebaseAppError.PrefixedFirebaseError [as constructor] (/app/node_modules/firebase-admin/lib/utils/error.js:90:28)
2021-05-17T00:37:50.367409+00:00 app[web.1]:     at new FirebaseAppError (/app/node_modules/firebase-admin/lib/utils/error.js:125:28)
2021-05-17T00:37:50.367415+00:00 app[web.1]:     at new ServiceAccount (/app/node_modules/firebase-admin/lib/credential/credential-internal.js:142:19)
2021-05-17T00:37:50.367415+00:00 app[web.1]:     at new ServiceAccountCredential (/app/node_modules/firebase-admin/lib/credential/credential-internal.js:68:15)
2021-05-17T00:37:50.367415+00:00 app[web.1]:     at Object.exports.cert (/app/node_modules/firebase-admin/lib/credential/credential.js:34:54)
2021-05-17T00:37:50.367416+00:00 app[web.1]:     at Object.<anonymous> (/app/firebase/db.js:22:34)
2021-05-17T00:37:50.367416+00:00 app[web.1]:     at Module._compile (internal/modules/cjs/loader.js:1068:30)
2021-05-17T00:37:50.367417+00:00 app[web.1]:     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
2021-05-17T00:37:50.367417+00:00 app[web.1]:     at Module.load (internal/modules/cjs/loader.js:933:32) {
2021-05-17T00:37:50.367417+00:00 app[web.1]:   errorInfo: {
2021-05-17T00:37:50.367417+00:00 app[web.1]:     code: 'app/invalid-credential',
2021-05-17T00:37:50.367418+00:00 app[web.1]:     message: 'Failed to parse private key: Error: Invalid PEM formatted message.'
2021-05-17T00:37:50.367418+00:00 app[web.1]:   },
2021-05-17T00:37:50.367418+00:00 app[web.1]:   codePrefix: 'app'
2021-05-17T00:37:50.367419+00:00 app[web.1]: }

我将密钥保存为.env 变量,该变量在我的本地主机上运行良好,并将其设置为带有heroku 的配置变量。 密钥的格式为:

-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY_HERE\n-----END PRIVATE KEY-----\n

我已经尝试了来自this thread 的所有修复以及我可以在此处和谷歌上找到的任何其他修复。我尝试过的不同组合如下:

//Method 1
process.env.PRIV_KEY.replace(/\\n/g, '\n')
//Method 2
JSON.parse(process.env.PRIV_KEY)
//Method 3
const { PRIV_KEY } = process.env
privateKey: PRIV_KEY[0] === '-' ? PRIV_KEY : JSON.parse(PRIV_KEY)

对于这些方法中的每一种,我都尝试将密钥包装在“”、“”、“”“”中,或者根本没有。这些方法都不适合我,我正在努力解决这个问题。如果有人发现不是其中之一的修复程序,请指出正确的方向。

【问题讨论】:

    标签: node.js heroku firebase-authentication


    【解决方案1】:

    我不确定您在方法 1 和方法 3 中要做什么。方法 2 是正确的,我只是尝试了它以确保它有效。只需确保您在 heroku 中添加的凭据是服务帐户 JSON 的字符串形式。您可以在本地运行它并对其进行字符串化。

    const stringifiedKey = JSON.stringify(theServiceAccountKeyObject)
    console.log(stringifiedKey)
    

    现在将这个字符串化的键复制到你的 heroku 环境变量中并像这样使用它:

    admin.initializeApp({
        credential: admin.credential.cert(JSON.parse(process.env.PRIV_KEY)),
        databaseURL: "https://<project-id>.firebaseio.com/"
    })
    

    您不必通过添加新行来格式化 JSON,或者我也不确定为什么 PRIV_KEY[0] 会成为 -。尝试按照我上面解释的方式对其进行字符串化,如果可行,请告诉我。

    编辑:您需要传递整个 JSON 对象,如下所示:

    {
        "type": "service_account",
        "project_id": "",
        "private_key_id": "",
        "private_key": "",
        "client_email": "",
        "client_id": "",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "",
        "client_x509_cert_url": ""
      }
    

    【讨论】:

    • 我试过了,它在本地工作,但不是通过 heroku。我尝试了几乎每种格式的键值来仔细检查,但它没有通过任何一种。任何其他想法为什么它不会接受它?为我的建议干杯,我很感激
    • @WillFletcher 你能在你的 Heroku 应用程序中尝试console.log(process.env) 并检查所有凭据是否都在那里吗?
    • @WillFletcher 知道了,您需要传递整个字符串化的 JSON 对象,而不仅仅是私钥,然后像上面显示的那样初始化应用程序
    • 所以你是说要对对象进行字符串化,然后在传递它后对其进行解析?我也试过了,它仍然给了我FirebaseAppError: Failed to parse private key: Error: Invalid PEM formatted message. 感谢您深入研究它,我真的不确定为什么这不起作用。我也刚用新钥匙试了一下,也有同样的问题。编辑:我控制台记录了该对象,它看起来就像那样。
    • 有什么解决办法吗?你解决了吗?
    【解决方案2】:

    实际上私钥没有被解析,因为它有转义字符,在某处改变了整体密钥值。

    你得到的service.json,应该改成环境变量,这样才能在heroku中作为环境变量推送。

    创建一个任意名称的文件

    const config = {
      dev: {
        type: process.env.TYPE,
        project_id: process.env.PROJECT_ID,
        private_key_id: process.env.PRIVATE_KEY_ID,
        private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'), 
        client_email: process.env.CLIENT_EMAIL,
        client_id: process.env.CLIENT_ID,
        auth_uri: process.env.AUTH_URI,
        token_uri: process.env.TOKEN_URI,
        auth_provider_x509_cert_url: process.env.AUTH_PROVIDER_X509_CERT_URL,
        client_x509_cert_url: process.env.CLIENT_X509_CERT_URL,
      },
    };
    

    注意这个

    - private_key: process.env.PRIVATE_KEY, <---- Wrong format
    + private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'), 
    

    .env 文件中的私钥应该是这样的

    PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nMII....
    

    加载您的 Firebase 凭据,例如 importedfile.dev

    现在已经成功解析,你的服务器可能会再次启动。

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 2017-08-26
      相关资源
      最近更新 更多