How do you best manage database URL in firebase cloud functions? - firebase

I have a dev database and a staging database and I want my firebase cloud functions to use whichever database is appropriate based on where it is deployed, is there a variable or something that I can reference for this so that I dont have to manually change the URL before every deploy to dev or staging environment?
var FirebaseDBUrlVar = 'some-url-to-firebase-dev';
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: FirebaseDBUrlVar,
});

Starting version version 1.0 of the firebase-functions SDK, you can initialize the SDK with no arguments, and it will automatically pick up all the defaults for your environment:
admin.initializeApp()
If you need to add a service account to that, you can parse the defaults out of process.env.FIREBASE_CONFIG and add the credential to it:
const serviceAccount = require('./service-account-credentials.json')
const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG)
adminConfig.credential = admin.credential.cert(serviceAccount)
admin.initializeApp(adminConfig)

Related

How to use firebase admin SDK in local Node.js scripts?

I'm trying to use the firebase admin sdk in a local node.js script file (outside of firebase-functions) in order to preform some auth and firestore operations.
But I get this error:
{"severity":"WARNING","message":"Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail"}
Error: Failed to determine project ID: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND
Admin SDK initialization:
const admin = await import('firebase-admin');
const serviceKey = require('path/to/serviceKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceKey),
databaseURL: 'https://{project}.firebaseio.com',
});
All the questions I've found on this error are regarding running firebase-functions locally, but I'm not trying to use firebase-functions, I'm only trying to use admin.auth and admin.firestore locally.
Am I missing something here?
It works with the codes below based on this documentation:
const admin = require('firebase-admin');
const serviceKey = require('./path/to/serviceKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceKey),
databaseURL: 'https://{project}.firebaseio.com'
});
I also saw this question, creating new Google Cloud project from current Firebase project and upgrading Firebase project plan to Blaze Plan fixed the problem.

Firebase.firestore vs admin.firestore

I'm learning GCP and in their Firestore, I'm confused with the difference of Admin.firestore & Firebase.firestore.
this is the code for admin:
const admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://<firestoreprojectnameurl>"
const db = admin.firestore();
});
while this is the code for the firestore
const { config } = require('./config');
const firebase = require("firebase");
firebase.initializeApp(config);
const db = firebase.firestore();
Please note that only 1 db at a time will work and for my current set-up I use the db = firebase.firestore() although if I change it to db = admin.firestore ite works fine and all my code works the same.
Thank you in advance!
The JavaScript SDK for web clients (your second example) is different than the JavaScript SDK for nodejs backends (your first example). They have different APIs, though they might appear very similar for most types of queries. But they are definitely not interchangeable. You are supposed to pick the one that matches the environment where it's going to be used. The Firebase Admin SDK is definitely not usable in web clients, though the web client SDK might work in nodejs backend environments (but I don't recommend it).
It might also help to know that the Firebase Admin SDK is actually just a wrapper around the Google Cloud nodejs SDK. You can compare the API documentation of the web SDK to the nodejs SDK if you want to take a closer look.

'auth/invalid-api-key' When Letting the Admin SDK discover a service account

In different pages of the Firebase Admin SDK documentation, e.g., this page, it is suggested that:
If your code is deployed in an environment managed by Google, the
Admin SDK can attempt to auto-discover... the service account
provisioned for your app...To make use of these signing methods,
initialize the SDK with Google Application Default credentials and do
not specify a service account ID string: admin.initializeApp();
When I do this, I get the following error message:
[Error: Your API key is invalid, please check you have copied it
correctly.] code: 'auth/invalid-api-key', message: 'Your API key
is invalid, please check you have copied it correctly.'
Note that I do not get this error message when I manually download and import the credentials and service account JSON files in my project.
Detailed information for reproduction of the error:
1- I'm deploying this on Cloud Functions using Firebase CLI. So, basically, I use firebase deploy.
2- Here is the minimal code in my Node.js App:
const admin = require("firebase-admin");
const config = require("./firebase-config");
admin.initializeApp();
const firebase = require("firebase");
firebase.initializeApp(config);
const functions = require("firebase-functions");
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
const cors = require("cors");
app.use(cors());
app.get("/", Some_Function);
exports.api = functions.https.onRequest(app);
The error happens when I replace firebase.initializeApp(config); with firebase.initializeApp();
You're trying to initialize the Firebase Client SDK in a server-side environment:
const firebase = require("firebase");
firebase.initializeApp(config);
The client SDK accepts a whole different set of credentials compared to firebase-admin. You can initialize firebase-admin without any arguments in GCP managed environments (e.g. Cloud Functions, Cloud Run), but the same doesn't apply to firebase. You need to provide a valid client app configuration obtained from your Firebase project.
const admin = require('firebase-admin');
admin.initializeApp(); // This is ok
const firebase = require('firebase');
firebase.initializeApp(); // This is wrong
See https://firebase.google.com/docs/web/setup#config-object for details on how to obtain a client app configuration.
Also please note that using the client SDK in an environment like Functions is rather unusual. I'd advise you rethink your use case, and see if you really need to use firebase client SDK in your function.
I have tried
dotenv did not work
process.env.PRIVATE_KEY.replace(/\\n/g, '\n') did not work
Step1: go to the console and generate new service account file
Step2: export GOOGLE_APPLICATION_CREDENTIALS='path/to/serviceAccount.json'
(it doesn't matter where it is, e.g : 'user/username/download/serviceAccount.json')
Step3: if(!admin.apps.length) admin.initializeApp(); In the docs, either export the json object as param or no param with step 2

Is firebase sevices.json needed for admin SDK on cloud functions

I am trying to write a function that writes to a different database when a user writes to the default database ,
I did my research and i am a little bit confused
I saw this on firebase
var admin = require('firebase-admin');
var serviceAccount =
require('path/to/serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL:
'https://<DATABASE_NAME>.firebaseio.com'
});
And also this
const app1 = firebase.initializeApp({
databaseURL: "https://testapp-1234-1.firebaseio.com"
});
const app2 = firebase.initializeApp({
databaseURL: "https://testapp-1234-2.firebaseio.com"
}, 'app2');
// Get the default database instance for an app1
var database1 = firebase.database();
// Get a database instance for app2
var database1 = firebase.database(app2);
So my question is do we need the service.json file which holds the secret key when using cloud functions admin SDK
For almost all typical use cases, you don't need to provide a service account when working with the Firebase Admin SDK in Cloud Functions. This is because Cloud Functions provides the credentials for the default service account in the project where the function is deployed. (This account can be seen as the App Engine default service account in the Cloud console.)
It's strongly recommended to initialize the Admin SDK with no arguments and accept this default account:
const admin = require('firebase-admin');
admin.initializeApp(); // accept the default service account
As part of taking this default, the Admin SDK will also understand the URL of your default Realtime Database shard, and the URL of your default Cloud Storage bucket. You won't need to provide these values. As such, your code will be much more easy to port to other projects.
If you need to access non-default resources of your project, you can also initialize other instances of firebase-admin to point to those that you explicitly configure. This is what your second code sample is illustrating. If you don't have any non-default resources to access, then don't bother with this.
If there is something that the service account can do, you can grant that role in the Cloud console. The one notable action that this account currently can't perform by default is cryptographic signing of blobs. In practical terms, this means it can't generate signed URLs for object stored in Cloud Storage. This is a fairly common thing to do in Cloud Functions. To remedy this, you need to grant the signBlob role to the default service account.

Firebase Admin SDK - Require is not defined

I'm currently looking through the Firebase documentation found here...
https://firebase.google.com/docs/admin/setup
... regarding how to initialise the Admin SDK.
I know the article states adding the Firebase Admin SDK to your SERVER - but how would I add this to my application as I am unsure how to add it to a server.
I have tried simply adding it to my index.js file but the console returns the
`Uncaught ReferenceError: require is not defined`
My code:
var admin = require("firebase-admin");
var serviceAccount = require("/Users/morgannwg/Downloads/<JSON NAME>.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<URL>.firebaseio.com"
});
Any ideas?
Many thanks,
G
You need to create Node.js server app. Here's an example: https://github.com/firebase/quickstart-nodejs

Resources