Using Firebase Admin SDK with Lambda Function

I’m trying to deploy some serverless Lambda functions that interact with the Firebase Admin SDK. I’ve been able to successfully test the functionality locally using the netlify-lambda local dev tools.

However, when I deploy to Netlify, I get an error:
Failed to parse private key: Error: Invalid PEM formatted message.

I assume this is something to do with the firebase admin trying to use the firebase private key which I have set in the environment variables using dotenv locally, and in the Netlify settings for deploys. This is the only difference between my two environments, I wrap the private key in double quotes ("") for dotenv to use, but do not use those double quotes ("") in the Netlify settings. I’ve tried changing this in the settings with no success.

Hoping someone else has successfully configured a serverless function with Firebase admin SDK using environment variables (rather than the default JSON file method).

my code:

import * as admin from 'firebase-admin'
import dotenv from 'dotenv'
dotenv.config()

const statusCode = 200
const headers = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'Content-Type'
}

const serviceCredential = {
  // ...
  private_key: process.env.FB_PRIVATE_KEY,
  // ...
}

admin.initializeApp({
  credential: admin.credential.cert(serviceCredential),
  databaseURL: 'https://DATABASE_NAME.firebaseio.com'
})

async function checkUser(uid) {
  try {
    console.log('passed uid: ', uid)
    const userRecord = await admin.auth().getUser(uid) // 1
    console.log('Rendered User: ', userRecord.toJSON())
    return userRecord.toJSON()
  } catch (error) {
    return `Error: ${error}`
  }
}

exports.handler = async (event, context, callback) => {
  const content = event.body
  const res = await checkUser(content)

  return {
    statusCode: statusCode,
    headers: headers,
    body: `checking user: ${res.displayName}`
  }
}

Per the recommendation of other posts in this community I’ve also tried deploying the function without the use of dotenv, and also used some regex text replacement for the private key because it has \n escaped characters by default.

And that was the secret combo to get this working! Downside is I have to have a different method for local env variables, but good news is I’m finally working with serverless functions!

For anyone else who runs into this problem, make sure the private key you’re passing into the service credential object is replacing these characters:

const serviceCredential = {
  // ...
  private_key: process.env.FB_PRIVATE_KEY.replace(/\\n/g, '\n'),
  // ...
}

Hi @AnthonyFromTheVault,

Welcome to the community and thank you for sharing your solution. Another option would be to BASE64 encode the key and then decode it in your function. You should also be able to use dotenv, it’s not clear to me why it wouldn’t work in this instance. Is it because you don’t get the same error locally? If you BASE64 encode the key then that error should no longer be an issue.

Thanks @futuregerald for the suggestion. I found that I could use dotenv while developing locally, and then simply copy-out that import/code when I was ready to push to production.

Hey @AnthonyFromTheVault

I came across the same problem and I ended up running the production variable through JSON.parse() to correctly format the key in production.

I continued to use dotenv for local and production env variables, with this ternary condition:

const { FB_PRIVATE_KEY } = process.env
const serviceCredential = {
  // ...
  privateKey: FB_PRIVATE_KEY[0] === '-' ? FB_PRIVATE_KEY : JSON.parse(FB_PRIVATE_KEY),
  // ...
}
2 Likes

Thank you for that suggestion @Jinksi, it’s a great one. :raised_hands:

1 Like

Thats a great solution @Jinksi, thanks!

1 Like