I'm trying to deploy an Express app to Heroku. The trouble I'm having is that Heroku or something along the way is screwing up the format of the RSA private key string. I have the following in my .env
which works locally and is kept out of git:
TYPE=
PROJECT_ID=
PRIVATE_KEY_ID=
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
CLIENT_EMAIL=
CLIENT_ID=
AUTH_URI=
TOKEN_URI=
AUTH_CERT_URL=
CLIENT_CERT_URL=
I initially used https://github.com/xavdid/heroku-config to set the above vars instead of doing it by hand through the dashboard on Heroku, but that private key failed.
Then I tried setting that value manually by copy/pasting (without double quotes) through the Heroku Dashboard, still failed.
Finally I set the value via heroku config:set
, but still fails to parse it when the app starts up.
I even tried replacing \n
with '\n'
as someone did here and using quotes with heroku config:set PRIVATE_KEY=""
, but still doesn't work.
So my question is, is Heroku doing something funky with the long string value? Or am I missing something. The above values are called/used as shown below:
const { credential } = require('firebase-admin')
exports.serviceAccount = {
type: process.env.TYPE,
project_id: process.env.PROJECT_ID,
private_key_id: process.env.PRIVATE_KEY_ID,
private_key: process.env.PRIVATE_KEY,
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_CERT_URL,
client_x509_cert_url: process.env.CLIENT_CERT_URL
}
exports.credential = credential.cert(exports.serviceAccount)
exports.databaseURL = process.env.DATABASE_URL
exports.adminConfig = {
credential: exports.credential,
databaseURL: exports.databaseURL
}
And logs from Heroku:
2017-06-05T01:50:13.761150+00:00 app[web.1]: > NODE_ENV=production node ./server/server.prod.js
2017-06-05T01:50:14.231853+00:00 app[web.1]: /app/node_modules/firebase-admin/lib/auth/credential.js:129
2017-06-05T01:50:14.231876+00:00 app[web.1]: throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse private key: ' + error);
2017-06-05T01:50:14.231877+00:00 app[web.1]: ^
2017-06-05T01:50:14.231878+00:00 app[web.1]:
2017-06-05T01:50:14.231878+00:00 app[web.1]: Error: Failed to parse private key: Error: Invalid PEM formatted message.
2017-06-05T01:50:14.231883+00:00 app[web.1]: at FirebaseAppError.FirebaseError [as constructor] (/app/node_modules/firebase-admin/lib/utils/error.js:39:28)
2017-06-05T01:50:14.231884+00:00 app[web.1]: at new FirebaseAppError (/app/node_modules/firebase-admin/lib/utils/error.js:84:23)
2017-06-05T01:50:14.231885+00:00 app[web.1]: at new Certificate (/app/node_modules/firebase-admin/lib/auth/credential.js:129:19)
2017-06-05T01:50:14.231886+00:00 app[web.1]: at new CertCredential (/app/node_modules/firebase-admin/lib/auth/credential.js:195:33)
2017-06-05T01:50:14.231887+00:00 app[web.1]: at Object.cert (/app/node_modules/firebase-admin/lib/firebase-namespace.js:189:58)
2017-06-05T01:50:14.231887+00:00 app[web.1]: at Object.<anonymous> (/app/server/firebase/index.js:16:33)
2017-06-05T01:50:14.231888+00:00 app[web.1]: at Module._compile (module.js:569:30)
2017-06-05T01:50:14.231888+00:00 app[web.1]: at Object.Module._extensions..js (module.js:580:10)
2017-06-05T01:50:14.231889+00:00 app[web.1]: at Module.load (module.js:503:32)
2017-06-05T01:50:14.231889+00:00 app[web.1]: at tryModuleLoad (module.js:466:12)
I was able to solve my issue using a comment suggestion I found here.
So on the Heroku dashboard for the app, I set the PRIVATE_KEY
value to be double quoted:
I then changed
private_key: process.env.PRIVATE_KEY
to
private_key: JSON.parse(process.env.PRIVATE_KEY)
and finally redeployed via git push heroku master
and the app started up fine.
2018-10-27: The comments from the link above are gone now. But essentially the commenter had mentioned that the string is effectively a JSON string which needs to be parsed back into a String
.
2019-08-01: The domain originally linked is no longer valid. So I have replaced the original link with one from the Wayback Machine.
Your key inside your .env
must be wrapped inside a single and double qoutes in the same time like this '"[PRIVATE_KEY]"'
which indeed the same format you will get from heroku when you call this command $ heroku config:get PRIVATE_KEY -s >> .env
One more thing to add to JSON.parse
in case it stills gets you an error which you will find in here:
Node.js -Firebase Service Account Private Key won't parse
So after you came back from that page, the final code line will look like this:
JSON.parse(process.env.PRIVATE_KEY).replace(/\\n/g, '\n')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With