Deploying Firebase App with Service Account to Heroku (environment variables with dotenv)

Luke Schlangen picture Luke Schlangen · Dec 22, 2016 · Viewed 7.3k times · Source

I have a node application that uses a firebase service account. I would like to deploy the app to Heroku, but I don't want to make my secret keys public. I am deploying directly from a public github repo, so I don't want to include the service account file in the deployment.

I can take the service account json file, make each property an environment variable, add each of those variables to Heroku and deploy it. Everything works great (after authorizing the new Heroku domain on my firebase application), but is there a better way to do this? This works, but it was kind of a pain to do (copying and pasting each variable and moving it). Am I missing an easier way to do this?

Here is the change I am making. From this line where it is pulling the credentials from a file:

admin.initializeApp({
  credential: admin.credential.cert('./path/firebase-service-account.json'),
  databaseURL: "https://my-firebase-app.firebaseio.com"
});

To this object that is bringing in all of the same things from environment variables:

admin.initializeApp({
  credential: admin.credential.cert({
    "type": process.env.FIREBASE_TYPE,
    "project_id": process.env.FIREBASE_PROJECT_ID,
    "private_key_id": process.env.FIREBASE_PRIVATE_KEY_ID,
    "private_key": process.env.FIREBASE_PRIVATE_KEY,
    "client_email": process.env.FIREBASE_CLIENT_EMAIL,
    "client_id": process.env.FIREBASE_CLIENT_ID,
    "auth_uri": process.env.FIREBASE_AUTH_URI,
    "token_uri": process.env.FIREBASE_TOKEN_URI,
    "auth_provider_x509_cert_url": process.env.FIREBASE_AUTH_PROVIDER_X509_CERT_URL,
    "client_x509_cert_url": process.env.FIREBASE_CLIENT_X509_CERT_URL
  }),
  databaseURL: "https://my-firebase-app.firebaseio.com"
});

Is this the best practice for deploying a firebase application with a service account to Heroku? I am using the dotenv node module to accomplish this.

Answer

Robert K. Bell picture Robert K. Bell · Jan 15, 2017

There's two mandatory fields for the cert options object: clientEmail and privateKey. Your example can be trimmed down to:

admin.initializeApp({
  credential: admin.credential.cert({
    "private_key": process.env.FIREBASE_PRIVATE_KEY,
    "client_email": process.env.FIREBASE_CLIENT_EMAIL,
  }),
  databaseURL: "https://my-firebase-app.firebaseio.com"
});

As an aside, some environments might have trouble with newlines in the private_key env var; I found key.replace(/\\n/g, '\n') to be a straightforward solution.