Saad8113
Saad8113

Reputation: 173

How to store an object in process.env variables

I'm using firebase in my node js. application, and I want to store its serviceAccountKey.json file in a process.env variable.

Something like this in my dotenv (.env) file

  SERVICE_ACCOUNT_KEY={
  "type": "anything",
  "project_id": "anything",
  "private_key_id": "anything",
  "private_key": "anything",
  "client_email": "anything",
  "client_id": "anything",
  "auth_uri": "anything",
  "token_uri": "anything",
  "auth_provider_x509_cert_url": "anything",
  "client_x509_cert_url": "anything"
}

But when I do this, It says

Service account must be an object.

Please help me storing this object in process.env variable.

Upvotes: 7

Views: 19961

Answers (4)

Samuel Earl
Samuel Earl

Reputation: 491

I ran into a similar issue while developing a SvelteKit app with Firebase Auth. SvelteKit has some features that protect from importing private environment variables into public code, which is what the import { FIREBASE_SERVICE_ACCOUNT_KEY } from "$env/static/private"; is all about (see below). If you are not using SvelteKit, then you can use process.env.FIREBASE_SERVICE_ACCOUNT_KEY like others have used in this thread.

This is what I did:

in my .env file:

FIREBASE_SERVICE_ACCOUNT_KEY = `{
  "type": "anything",
  "project_id": "anything",
  "private_key_id": "anything",
  "private_key": "anything",
  "client_email": "anything",
  "client_id": "anything",
  "auth_uri": "anything",
  "token_uri": "anything",
  "auth_provider_x509_cert_url": "anything",
  "client_x509_cert_url": "anything"
}`

Since environment variables need to be strings, I wrapped the object in back ticks. However, it doesn't appear that you have to use back ticks because this also worked for me when I used single quotes too. And I was able to preserve the multi-line object structure with both back ticks and single quotes.

In my /lib/firebase/server/index.ts file (which is just a server-side file):

import { cert, getApps, initializeApp } from "firebase-admin/app";
import { getAuth } from "firebase-admin/auth";
import { FIREBASE_SERVICE_ACCOUNT_KEY } from "$env/static/private";

// Initialize Firebase Admin for a SvelteKit app.
function makeApp() {
  const apps = getApps();
  if (apps.length > 0) {
    return apps[0]!;
  }

  return initializeApp({
    credential: cert(JSON.parse(FIREBASE_SERVICE_ACCOUNT_KEY)),
  });
}

export const firebase = makeApp();
export const auth = getAuth(firebase);

Some Notes About Production Deployments:

If you are wondering whether you should store your private key in a public repository, like GitHub, or not, this should be helpful. When you generate a new private key, Google gives you this warning:

Your private key gives access to your project's Firebase services. Keep it confidential and never store it in a public repository.

I have seen some tutorials that have you separate each property of the FIREBASE_SERVICE_ACCOUNT_KEY into separate environment variables and then import and reference each of those environment variables individually. That gets a little messy, especially when you want to store your environment variables in your web host's environment variables storage.

The approach I used, with back ticks and JSON.parse(), also allowed me to easily store these variables in my web host's environment variables storage. Just remember that when you store the JSON object for FIREBASE_SERVICE_ACCOUNT_KEY in your web host's environment variables storage, do NOT include the back ticks (or single quotes) around the object. I accidentally did that and got strange errors that took me a while to debug.

Upvotes: 1

Md Shah Jalal
Md Shah Jalal

Reputation: 87

In .env file:

MY_VAR='{"a":"valueA","b":"valueB"}'

In app.js file:

const serviceAccount = JSON.parse(process.env.MY_VAR);

instead of

const serviceAccount = require(JSON.parse(process.env.MY_VAR));

remove require and ().

Sample: enter image description here

Upvotes: 1

Luca Galasso
Luca Galasso

Reputation: 161

When storing a variable in the process.env, it will be automatically converted as a string.

Given that, if you'd like to set a variable in the process.env, either you pass a proper string object-like while running your script:

SERVICE_ACCOUNT_KEY='{"type":"anything"}' node script.js

or you cast the object to a string in your script.js file like:

process.env.SERVICE_ACCOUNT_KEY = JSON.parse(SERVICE_ACCOUNT_KEY)

In both cases, while reading your variable from the process.env, you should convert it to an object:

SERVICE_ACCOUNT_KEY = JSON.parse(process.env.SERVICE_ACCOUNT_KEY)

Since the error you wrote says "... must be an object.", most probably the missing piece is the last step (parsing from string to object).

Upvotes: 0

tdonnenfeld
tdonnenfeld

Reputation: 121

You could try to store the object as a string and parse it as JSON in your code.

.env :

MY_VAR='{"a":"valueA","b":"valueB"}'

Then in the code
app.js :

let object = JSON.parse(process.env.MY_VAR);

EDIT ( thanks @Luca Galasso ) Reformed a correct JSON string.

Upvotes: 6

Related Questions