9

I need to create a Cloud Function that will access the Firebase DB that is running in another project. If it was accessing the db in the current project, I could use code such as

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

however, what I want is for functions.config().firebase to return the information (and, most importantly, credentials) for the other project. Is there any easy way to do this?

Prisoner
  • 49,922
  • 7
  • 53
  • 105

3 Answers3

10

functions.config().firebase is a reserved namespace and you won't be able to override it. However, you can do cross-project initialization yourself. Here's how I would do it:

First, download a service account for your other project into your functions directory. Name it <project_id>-sa.json. Next, set up some environment config (app.other_project_id is just an example name, not a requirement):

firebase functions:config:set app.other_project_id="<the_project_id>"

Now in your code, you can initialize the Admin SDK like so:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

if (!functions.config().app || !functions.config().app.other_project_id) {
  throw new Error('Cannot start app without app.other_project_id config.');
}

const FB_PROJECT_ID = functions.config().app.other_project_id;
const SERVICE_ACCOUNT = require(`./${FB_PROJECT_ID}-sa.json`);

admin.initializeApp({
  databaseURL: `https://${FB_PROJECT_ID}.firebaseio.com`,
  credential: admin.credential.cert(SERVICE_ACCOUNT)
});

This will have initialized the Admin SDK for the other project.

AKd
  • 501
  • 4
  • 17
Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • Thanks. This was along the lines of what I feared I would have to do. I was avoiding it because (1) All my other configuration is in... Firebase DB. So putting just one thing in functions.config() was annoying. (2) I prefer to avoid using (and deploying) files that shouldn't be in revision control. But I suspect this will be roughly be the solution I'll go with. – Prisoner May 12 '17 at 22:38
  • This approach works really well if you want to implement a REST API hosted in another Firebase project, and need to consume information of another Firebase project. – amouly May 23 '17 at 02:55
  • 2
    It is probably a terrible idea to push those json credentials into a repo. – Pier Mar 02 '18 at 01:45
  • 2
    Yup. `.gitignore` is your friend here – Michael Bleigh Mar 02 '18 at 18:33
  • Could you specify what would happen if I have admin.intializeApp() on my global scope and then initialize another app? Would my other firebase-admin imports break? – delpo Oct 21 '20 at 21:25
  • 4
    @MichaelBleigh, isn't it feasible to grant [Firebase Realtime Database roles](https://firebase.google.com/docs/projects/iam/roles-predefined-product#realtime-database) in the project B to the [service account `project-id@appspot.gserviceaccount.com`](https://firebase.google.com/support/guides/service-accounts) of the project A that is [used for running cloud functions](https://stackoverflow.com/a/56618369/3082178) to avoid explicitly specifying credential? – AKd Dec 23 '20 at 07:55
  • 3
    @AKd yes, you should be able to grant cross-project roles for this purpose. That would be an alternative way to do the above. – Michael Bleigh Dec 25 '20 at 00:10
1

2023 ANSWER:

You can initialize multiple Admin apps in a Cloud function as shown below:

// Initialize the default app
initializeApp(defaultAppConfig);
const otherApp = initializeApp(otherAppConfig, 'other');

const defaultFirestore = getFirestore();
const otherFirestore = getFirestore(otherApp);

Here you can use defaultFirestore to read from first Firestore project and then otherFirestore to write in another.

TinyTiger
  • 1,801
  • 7
  • 47
  • 92
-1

instead of

if (!functions.config().app || !functions.config().app.project_id) {

You should use

if (!functions.config().app || !functions.config().app.fb_project_id) {

NOTE: the typo in project_id

Robert Mengual
  • 374
  • 3
  • 10