How do I add Google Application Credentials/Secret to Vercel Deployment?
Asked Answered
A

5

15

I am using Vercel Deployments with a NextJS app. Deployments are automatically run when I push to master, but I don't want to store keys in GitHub. My serverless functions are reliant on my database. When run locally, I can simply use Google's Default Authentication Credentials, but this is not possible when deployed to Vercel. As such, I created a Service Account to enable the server to have access.

How do I load the service account credentials without pushing they key itself to GitHub?

Attenuation answered 26/9, 2020 at 2:5 Comment(1)
F
10

Rather than using a path to a JSON file, you can create an object and include environment variables as the values for each object key. For example:

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

Then, you can add the environment variables inside your project settings in Vercel.

Fdic answered 7/10, 2020 at 2:55 Comment(4)
github.com/vercel/vercel/issues/749#issuecomment-715009494Slimsy
this doesn't work in new versions of firebase, In case you're aware of the same can you update it?Desdamona
Same here, were you were able to solve it? It seems to me that were some changes to the class and now it says googleapis__WEBPACK_IMPORTED_MODULE_0__.google.auth.GoogleAuth is not a constructorPalstave
Ensure the private_key is a JSON-compliant value by wrapping it in an extra double quote FIREBASE_PRIVATE_KEY='"-----BEGIN PRIVATE KEY-----\nXXX\n-----END PRIVATE KEY-----"' And parse the value on retrieval, like so: JSON.parse(process.env.FIREBASE_PRIVATE_KEY) Reference: github.com/vercel/vercel/issues/749#issuecomment-707515089Accustom
K
3

Based on @leerob's and @Erem's answers, I just verified that the following code works while testing with Node.js v20.5.1 and [email protected] both locally and on Vercel.

Start by setting up environment variables locally for the following:

FIREBASE_CLIENT_EMAIL="firebase-adminsdk-[REDACTED]@[REDACTED].iam.gserviceaccount.com"
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nXXX\nYYY\nZ==\n-----END PRIVATE KEY-----"
FIREBASE_PROJECT_ID="[REDACTED]"

Store the contents of those very same environment variables in Vercel, but without the surrounding double-quotes

Then use this code:

import {
  cert,
  initializeApp,
} from 'firebase-admin/app';

initializeApp({
  credential: cert({
    client_email: process.env.FIREBASE_CLIENT_EMAIL,
    private_key: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
    project_id: process.env.FIREBASE_PROJECT_ID,
  }),
  databaseURL: `https://${process.env.FIREBASE_PROJECT_ID}.firebaseio.com`,
});

Now you should be able to do things like…

import { getAuth } from 'firebase-admin/auth';

const user = await getAuth().getUser(someUserId);
Keli answered 13/10, 2023 at 1:27 Comment(0)
I
1

I had this problem too but with google-auth-library. Most of Googles libraries provide a way to add credentials through a options object that you pass when initializing it. To be able to get information from Google Sheets or Google Forms you can for example do this:

const auth = new GoogleAuth({
  credentials:{
    client_id: process.env.GOOGLE_CLIENT_ID,
    client_email: process.env.GOOGLE_CLIENT_EMAIL,
    project_id: process.env.GOOGLE_PROJECT_ID,
    private_key: process.env.GOOGLE_PRIVATE_KEY      
  },
  scopes: [
    'https://www.googleapis.com/auth/someScopeHere',
    'https://www.googleapis.com/auth/someOtherScopeHere'
  ]
});

You can just copy the info from your credentials.json file to the corresponding environment variables. Just take care that when your working on localhost you will need to have the private_key in double quotes but when you put it into Vercel you should not include the quotes.

Implantation answered 21/9, 2022 at 11:16 Comment(0)
R
0

Adding to @leerob's answer, I found that putting quotes around the FIREBASE_PRIVATE_KEY environment variable in my .env file fixed an error I kept getting relating to the PEM file when making a request. I didn't need any quotes around the key for calls to the standard firebase library though.

This was the config I used to access the Google Cloud Storage API from my app:

const { Storage } = require('@google-cloud/storage');

const storage = new Storage({ projectId: process.env.FIREBASE_PROJECT_ID,
                              credentials: { client_email: process.env.FIREBASE_CLIENT_EMAIL,
                                              private_key: process.env.FIREBASE_PRIVATE_KEY_WITH_QUOTES
                                            } 
                            })
Re answered 16/12, 2021 at 4:28 Comment(0)
S
0

Just wanting to add an answer to recommend the Google Cloud Platform community integration for vercel that made this so easy for me: https://www.gcpvercel.com/

You simply install the integration on your vercel deployment: https://vercel.com/integrations/gcp/new

The UI then takes you through uploading your Google Application Credentials JSON file to vercel, and the creds are automatically available as environment variables on your deployment(s) without having to manually add them.

Copy the kickoff code provided to auth your application and it works from there.

export const getGCPCredentials = () => {
  // for Vercel, use environment variables
  return process.env.GCP_PRIVATE_KEY
    ? {
        credentials: {
          client_email: process.env.GCP_SERVICE_ACCOUNT_EMAIL,
          private_key: process.env.GCP_PRIVATE_KEY,
        },
        projectId: process.env.GCP_PROJECT_ID,
      }
      // for local development, use gcloud CLI
    : {};
};

Example

import { Storage } from '@google-cloud/storage';

export const storageClient = new Storage(getGCPCredentials());

const bucketName = 'my-bucket';
const fileName = 'my-file.json';
const file = storageClient.bucket(bucketName).file(fileName);

await file.save(JSON.stringify({
  foo: 'bar',
}), {
  contentType: 'application/json',
});

Firestore example

import { Firestore } from '@google-cloud/firestore';

const firestore = new Firestore(getGCPCredentials());
const document = firestore.doc('posts/intro-to-firestore');

await document.set({
  title: 'Welcome to Firestore',
  body: 'Hello World',
});

console.log('Entered new data into the document');
Sloganeer answered 6/6 at 5:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.