Reputation: 173
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
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
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 ().
Upvotes: 1
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
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