DEV Community

Vincent Voyer
Vincent Voyer

Posted on

How to add Firebase service account json files to Vercel

If you're using Firebase, Next.js, Vercel, firebase-admin, and if you've been Googling for the past hour on how to load your Google service account JSON file the easiest way possible, then you've come to the right place.

This blog post explains how to store the service account json file in a single environment variable and then pass it down to the Firebase admin SDK.

Here's how to do it:

1. Download the service account JSON file

Follow the steps at https://firebase.google.com/docs/admin/setup and download the JSON file.

2. Remove line breaks on the JSON file

Go to https://www.textfixer.com/tools/remove-line-breaks.php and paste the content of the JSON file.

Do not remove the \n characters from the private_key fields or the key won't be valid afterwards.

3. Create a new Vercel environment variable with the JSON content

Either via a command line:

vercel env add FIREBASE_SERVICE_ACCOUNT_KEY
? What’s the value of FIREBASE_SERVICE_ACCOUNT_KEY?
Enter fullscreen mode Exit fullscreen mode

(paste the JSON content and submit)

Or via the Vercel web ui: https://vercel.com/docs/environment-variables

In both cases, the value will be encrypted.

4. Use it locally in .env.local

This is the tricky part, because you have to use single quotes instead of double quotes when surrounding the environment variable value in your file.

I am using the gitignored .env.local as explained in the Next.js documentation: https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables.

# .env.local
FIREBASE_SERVICE_ACCOUNT_KEY='JSON file content without line breaks'
Enter fullscreen mode Exit fullscreen mode

5. Use the environment variable

Here's an example Next.js api route that will receive a Firebase id token and verify it. See https://firebase.google.com/docs/auth/admin/verify-id-tokens#web

// pages/api/user.ts

import * as admin from "firebase-admin";
import type { NextApiRequest, NextApiResponse } from "next";

type Data = {
  uid: string;
};

const serviceAccount = JSON.parse(
  process.env.FIREBASE_SERVICE_ACCOUNT_KEY as string
);

if (admin.apps.length === 0) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
  });
}

// example usage 
export default async function revenueCatApi(
  req: NextApiRequest,
  res: NextApiResponse<Data>
): Promise<void> {
  const firebaseToken = req.headers?.authorization?.split(" ")[1];

  if (!firebaseToken) {
    res.status(404).end();
    return;
  }

  const decodedToken = await admin.auth().verifyIdToken(firebaseToken);

  res.status(200).json({ uid: decodedToken.uid });
}
Enter fullscreen mode Exit fullscreen mode

That's it! Hope this helps.

Oldest comments (8)

Collapse
 
eullerpeixoto profile image
Euller Peixoto

Hey, thanks a lot! You're now my hero! xD

Collapse
 
pablomdd profile image
Pablo Domínguez Durán

This was really helpful. My use-case was more into a GoogleApi but the key concepts remain the same. Thanks!

Collapse
 
abdurrehman1998 profile image
abdurrehman1998

Very Good, been looking for it. Thanks

Collapse
 
iamrahulrnair profile image
Rahul R

Man u saved my day!!!

Collapse
 
mirozone profile image
Amir

Thank you alot

Collapse
 
offchan profile image
Chanchana Sornsoontorn

Works like a charm

Collapse
 
aiisawesome profile image
ai-is-awesome

I just created my account here to say THANK YOU. I've been stuck on deployment due to google's weird way of implementing apis. I literally had to create a new private repo and push my credentials json there to test the deployment but I was still getting file not found error for some reason. Tried your way and it fixed so many problems, no need to maintain a json file and the deployment worked too!

Collapse
 
nachpok profile image
Nachliel

Your a lifesaver