Home > Net >  Firebase multiple real time databases, custom auth issues
Firebase multiple real time databases, custom auth issues

Time:07-16

I'm attempting to use multiple real time databases for my single project in Firebase. For my setup, I'm generating tokens and sending to users from a server that is not part of Google's servers.

Everything works so far for the default database, but issues arise when attempting access the second real time database. I have read that it might be because you have to generate a token for each app instance, but to avoid becoming a difficult process, is it possible to generate a single token that can access all databases?

On my backend server we do this to generate a token:

initializeApp({
        credential: admin.credential.cert(FirebaseCredentials),
});

usually the next line is a databaseURL. What is passed the service account JSON file.

Is there an easy way to allow a user to use one token to access all databases if we had 10 of them or is the solution to initalizeApp and specify a different database each time with 10 different tokens if the data is spread across 10 different real time databases.


Client side I used the generated token to sign up. The generated token does not specify a databaseURL and appears to use the default database. When I attempt to use the second database, I tried to follow the multi database instructions.

const app2 = initializeApp({ databaseURL: '...'}, 'app2');
const db = getDatabase(app2);
set(ref(db, 'users'), {
   user: 'me',
});

When I use that second one, I get hit with permissions denied. The rules are identical between rtdbs. I'm guessing its because my original app config token is for the default database and not for the new one? Is it possible to somehow use a single generated token for all databases?

Firebase Rules for both databases.

{
  "rules": {
    ".read": "auth.token.chatEnabled === true",
    ".write": "auth.token.chatEnabled === true"
  }
}

Here is how I use the token on client side. I simply pass the token back from the server. Client uses the Javascript SDK to initialize app with the firebase config generated from initial startup.

Then I do:

import { initializeApp } from "firebase/app";
import { getDatabase, ref, set } from 'firebase/database';

const firebaseConfig = {
... the config
};

const app = initializeApp(firebaseConfig);

const auth = getAuth();
await signInWithCustomToken(auth, token);
const app2 = initializeApp({
  databaseURL: 'secondatabaseurl'
}, 'app2');
const db = getDatabase(app2);
  set(ref(db, 'users'), {
  user: 'me',
});

I believe my issue arises because when I go to call the second app, the token generated appears to be only usable for the first app or default config.

If all of my databases are on a single project, do I have to create a separate app for each new database? If so, would that mean I need a separate token for each app instance or to sign into each app instance with the same token?

Thank you for your time.

CodePudding user response:

Not the answer, but I can initialize 2 different apps.

This works ->

const secondaryApp = initializeApp({ appconfig2 }, 'secondaryApp');
const auth = getAuth(secondaryApp);
const db = getDatabase(secondaryApp);
await signInWithCustomToken(auth, token);
set(ref(db, 'users'), {
  user: 'me',
});

This does not work ->

const secondaryApp = initializeApp({ appconfig2 }, 'secondaryApp');
const auth = getAuth(secondaryApp);
await signInWithCustomToken(auth, token);
const db = getDatabase(secondaryApp);
set(ref(db, 'users'), {
  user: 'me',
});
// now try a second database
 const db2 = getDatabase();
   set(ref(db2, 'users'), {
   user: 'me',
 });

From my understanding, getDatabase() pulls from the default initalizedApp. It appears that once a user has authenticated using one of the initializedApps (in this case the user initialized with secondaryApp), those authenticated details are not shared with other apps at least I'm not exactly sure how to share them with all apps declared. Even if the app configs have identical api keys, auth domains, etc but differ on the DatabaseURL, they do not somehow just connect.

Ideally once a user has authenticated, it should be that they have access to all databases in the single project/app, but this does not seem to be the case here.

The last response here might be the answer ->

Got permission denied when writing to the second instance of Firebase realtime database

So in order to access another database, a user must authenticate individually?

CodePudding user response:

Okay so that link at the end was the answer, I just didn't expect to have to do this.

If you specify auth for each database, since the databases are declared in different apps, you have to authenticate the user with each one before being able to read/write.

In other words, to make it work I had to signInWithCustomToken per each database instance.

const app1 = initializeApp(config1);
const app2 = initializeApp(config2);
const auth1 = getAuth(app1);
const auth2 = getAuth(app2);
await signInWithCustomToken(auth1, token);
await signInWithCustomToken(auth2, token);

then you can use each app instance to getDatabase(app1/app2).

Maybe the reason for this is that people can use completely different apps. Maybe there is some way in future to make it so that one app with multiple sharded real time databases do not require authentication into each app database. Maybe it would be instead of declaring a new app for each sharded db, it should be some other helper function.

  • Related