63

I use .env variables in my app.js file to access the keys. Everything was working fine until I downloaded a new Firebase Service Account Private Key. When I replaced the old value with the new value I can no longer access the key because in terminal when I run node app.js I keep getting an error message:

/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/auth/credential.js:129 throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse private key: ' + error); ^

Error: Failed to parse private key: Error: Invalid PEM formatted message. at FirebaseAppError.FirebaseError [as constructor] (/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/utils/error.js:39:28) at FirebaseAppError.PrefixedFirebaseError [as constructor] (/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/utils/error.js:85:28) at new FirebaseAppError (/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/utils/error.js:119:28) at new Certificate (/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/auth/credential.js:129:19) at new CertCredential (/Users/Cpu/Desktop/...../node_modules/firebase-admin/lib/auth/credential.js:192:64) at Object.cert (/Users/Cpu/Desktop/.....) at Object. (/Users/Cpu/Desktop/...../app.js:14:32) at Module._compile (module.js:571:32) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:488:32) at FirebaseAppError.FirebaseError [as constructor] npm ERR! code ELIFECYCLE npm ERR! errno 1

All I did was c+p the new Private Key and then added it and saved the .env file, pushed to heroku, and it's no longer working. I even downloaded a new Private Key but the same problem occurs.

The old and new Private Keys

// old Private Key
-----BEGIN PRIVATE KEY-----\nbbbbbbbb\n-----END PRIVATE KEY-----\n

// new Private Key
-----BEGIN PRIVATE KEY-----\nzzzzzzzz\n-----END PRIVATE KEY-----\n

The .env file:

FIREBASE_PROJECT_ID=wwwwwwww
FIREBASE_CLIENT_EMAIL=xxxxxxxx
FIREBASE_DATABASE_URL=yyyyyyyy
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nzzzzzzzz\n-----END PRIVATE KEY-----\n

The app.js file:

const dotenv = require('dotenv');
dotenv.load();

var admin = require("firebase-admin");
admin.initializeApp({
  credential: admin.credential.cert({
      projectId: process.env.FIREBASE_PROJECT_ID,   // I get no error here
      clientEmail: process.env.FIREBASE_CLIENT_EMAIL,   // I get no error here
      privateKey: process.env.FIREBASE_PRIVATE_KEY   // I get error HERE
  }),
  databaseURL: process.env.FIREBASE_DATABASE_URL
});

How can I fix this issue?

6 Answers 6

195

The problem was since I used dotenv variables inside the .env file the FIREBASE_PRIVATE_KEY had escaping characters: \n inside of it.

I had to follow this answer and append .replace(/\\n/g, '\n') to the end of it to parse it:

privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n')

So now the code looks like:

admin.initializeApp({
  credential: admin.credential.cert({
      projectId: process.env.FIREBASE_PROJECT_ID, // I get no error here
      clientEmail: process.env.FIREBASE_CLIENT_EMAIL, // I get no error here
      privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n') // NOW THIS WORKS!!!
  }),
  databaseURL: process.env.FIREBASE_DATABASE_URL
});
11
  • 1
    I'm having this problem after creating new keys in Firebase. I'm keeping the key values in Firebase Environmental Variables, so I shouldn't have to adjust for \n. When I firebase deploy --only functions, I get the PEM error. Any suggestions?
    – Chadd
    Nov 5, 2018 at 19:26
  • I never user Firebase env vars before. I wish I could help Nov 5, 2018 at 19:52
  • This solved my issue. Strange thing was it worked without it, then suddenly stopped working. Anyway, voted this up for others to see. Dec 1, 2018 at 5:43
  • @PatrickMichaelsen the same exact thing happened to me. It was working without it then for some strange after I changed to a new private key and tried again it no longer worked. Very odd. Anyway glad I could help and thanks for the upvote. Cheers! Dec 1, 2018 at 5:45
  • 3
    I had same situation on AWS elastic beanstalk, I added \\n instead of \n in the environment variables and added replace where I access them. Jul 17, 2020 at 12:30
39

You must add your key into double qoutes to allow expanded new lines option according with dotenv documentation.

You can check that option at Rules section in dotenv github.

https://github.com/motdotla/dotenv#rules

  FIREBASE_PROJECT_ID=wwwwwwww
  FIREBASE_CLIENT_EMAIL=xxxxxxxx
  FIREBASE_DATABASE_URL=yyyyyyyy
  FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nzzzzzzzz\n-----END PRIVATE KEY-----\n"
0
2

Update : 2022

If anyone still looking for solution with below configurations, here's how I solved it.

Stack:

TypeScript Express Dotenv Heroku

CONVERT THE ENTIRE JSON FILE TO BASE64

Use this link to convert Base64 Encoder or you can use any other tools as well.

Add the Encoded String in your .env

FIREBASE_API_KEY=<your_large_base64_string>

Then below is the code for firebase-init.ts to consume the keys.

import * as admin from 'firebase-admin';

declare var process: {
    env: {
        FIREBASE_KEYS: string;
    }
}
const initializeFirebaseAdmin = (isProd = true) => {
    const firebase_private_key_b64 = Buffer.from(process.env.FIREBASE_KEYS, 'base64');
    const firebase_private_key = firebase_private_key_b64.toString('utf8');
    admin.initializeApp({
        credential: admin.credential.cert(JSON.parse(firebase_private_key))
    });
}


export { initializeFirebaseAdmin }
1
  • 1
    To keep your app secure, don't share your private key with untrusted third parties. There's also no need to convert to /from base 64, as previous answers show.
    – warfield
    Aug 7, 2022 at 12:14
0

I believe cert function is wating JSON object try converting the key into JSON and i think it will work

credential: admin.credential.cert(JSON.parse(serviceAccountKey))

this worked for me !

2
  • 2
    it shows SyntaxError: Unexpected token o in JSON at position 1 Mar 13, 2020 at 10:02
  • 1
    @PiyushPandey I had the same issue. I'm using dotenv and I was requiring dotenv after the file i was using it in, so that fixed it for me. Might be unhelpful, but just letting you know that's what did it for me! Jan 7, 2021 at 1:14
0

For me I just put the whole service acount in my .env file like so:

.env

FIREBASE_ADMIN_API={"type":..."private_key":"..."...}

Then I import it like so:

server.ts

const firebase_admin_config = JSON.parse(process.env.FIREBASE_ADMIN_API);

getApps().length === 0 ? initializeApp({
  credential: credential.cert(firebase_admin_config)
}) : getApp();
-3

Generate admin SDK Firebase under Firebase > Settings > Admin SDK Firebase. Go to Google Cloud Platform in your project, click in IAM administrator > Source account, and generate the key code in account service (your account service is generated in the admin SDK Firebase).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.