How to configure Flutter apps to share Cloud Firestore - firebase

I have 2 Flutter applications -- let's call them A and B.
Each application uses Firebase Authentication and Firebase Analytics (and maybe more Firebase services in the future).
Both applications need to access a shared Cloud Firestore, and that access obviously needs to be secure.
So how can I best do this?
I have created 3 Firebase Projects:
Project A for Flutter application A -- enabled Auth and Analytics
Project B for Flutter application B -- enabled Auth and Analytics
Project C for Cloud Firestore
For the two Flutter applications, I have downloaded the respective GoogleService-Info.plist files and placed them in the project's ios/Runner directory. Each application can successfully login and capture analytics events, and I can clearly segregate activity between the two applications.
Now, I need to point both A and B to C. I first thought that I could simply update the DATABASE_URL in both GoogleService-Info.plist files, but that doesn't seem to work.
I have read the Configure multiple projects
documentation, and I can imagine having a secondary GoogleService-Info.plist file for the Cloud Firestore, perhaps named GoogleService-Info-DB.plist, but then how does one get FirebaseApp to load the secondary configuration? (Note that iOS needs to load the secondary plist, and Android needs to load a secondary json file.) I only see a configure method that accepts a FirebaseOptions class.
Related, I need to secure Project C's database to only authenticated users from Project A or Project B. How can I do that?

Related

Firebase function listening on project A, writing to project B

I have two Firebase projects, A and B. When a user follows another user on Project A, data is written to /followers/{followedUid}/{followerUid}. I would like to perform this same update to Project B.
Users of Project A aren't (can't be) authorized to write to Project B, so I need to use a cloud function. I already do things like this with Node.js functions and firebase-admin using service accounts, but here I want to use a function deployed to Firebase.
How can I add or reference a service account, or otherwise authorize a second project in a Firebase cloud function?
If you've already done this with a local Node.js process and service account, the process within Cloud Functions is going to be pretty similar.
You'll need to initialize the Admin SDK with the credentials (in the form of a JSON file that you deploy with the code) for project B, and then use that for writing the data.
Also see the Firebase documentation on initializing the Admin SDK.

Google App Engine from project A cannot use Firebase Cloud Messaging from project B

We are running 2 separate Google Cloud Projects, Project A and Project B.
Project A is currently running an App Engine (AE) based API.
The API on project A needs to access the Firebase features on project B.
✅ I have setup cross projects access between the two projects using IAM and most functions are working fine.
App Engine on project A is able to access the Firebase real time db (RTDB) and Firebase Auth functions on Project B.
But we are unable to connect to Firebase Cloud Messaging on Project B
As far as I can see tracing through the Firebase admin SDK calls, we are able to obtain access tokens, and they're all valid as we can use some of the services (i.e. RTDB, Auth)
However, when we try using Firebase Cloud messaging we receive the following error: An error occurred when trying to authenticate to the FCM servers. Make sure the credential used to authenticate this SDK has the proper permissions.
Which seems to originate from a 401 unauthorized response to this service https://iid.googleapis.com/iid/v1:batchAdd
It doesn't seem to matter what amount of Roles on Project B I throw at the Project A service account.
If I use a separate Firebase service account that originated from Project B and use that json file as a credential then the issue go away, but I don't want to distribute credential files around, and everything else work fine without, except FCM.
FWIW this is how i initialise the firebase admin sdk
const firebaseAdmin = require('firebase-admin');
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.applicationDefault(),
projectId:'project-b',
databaseURL: "https://project-b.firebaseio.com",
});
I've also tried setting the serviceAccountId option to the project B service account email that works when manually loaded, but that doesn't change anything (also added Service Account Token Creator role)
The services account has also been given all the permissions listed here https://firebase.google.com/docs/projects/iam/permissions#messaging
Feels like there's a simple connection missing (either a role, or API setting) but I've ran out of idea.
Has anyone done this before and can provide some guidance?
EDIT [CORRECTED IN EDIT 3] I've also tried to manually create a service account on Project B with the same working roles as the Firebase service account that works and i'm getting the same issue (even though it was created on Project B). So sounds like maybe it's not a role issue, nor a cross-project issue?
EDIT 2 I'm on Node Js with latest firebase admin sdk
EDIT 3 Ignore the first edit, i hadn't configured the custom service account correctly, works fine with a service account created from scratch in Project B. So back to cross-project issue then I guess..
So in the case of Real time database, you only need to give Firebase Realtime Database Admin role to the Project A's App Engine service account on Project B.
In Firebase Cloud Messaging you can give Firebase Cloud Messaging Admin role on Project B AND the cloudmessaging.messages.create permission to the service account on Project A.
This will go around the initial 401 unauthorised response from messaging calls.
However, this will still result in an error, this time NOT FOUND, which indicates that the subscription token was not found.
It seems that calls to FCM don't use the projectId setting in firebase admin initialisation and always execute against the project the service account was created in (Project A in this case).
I haven't been able to find a way for FCM calls to executed in the specified projectId scope from another project.

Google App Engine access firebase in different project

I have setup app engine and firebase at PROJECT A, the app engine used default credentials, and able to access firebase at PROJECT A, however the app engine also need to call
verifyIdToken()
to verify user in PROJECT B.
What would be the best approach to it?
I can download the firebase credentials from PROJECT B, and use firebase admin sdk to do so, but it seems overkill, because i only needs to verify use token.
Setup firebase IAM permission in PROJECT B for app engine from PROJECT A, so it can access to firebase, theoretically, but in this case, how the app engine get the credentials from firebase in PROJECT B? Definitely not default credentials, right?
You can add the necessary roles from Project B to the service account used by Cloud Functions (it will be <project-a>#appspot.gserviceaccount.com). You would do this by visiting the Google Cloud IAM console in Project B and assigning the roles appropriately.
Once you do that, you should be able to use default credentials to authorize requests for Project B.
Note: There's some nuance here and I haven't directly tried this, but it should work in theory.
Found the solution
using_a_service_account_id
and
Answer from another post
After setup the IAM role and policy in project B with project A accouint, simply just do
projectB_firebase = firebase_admin.initialize_app(options={
"serviceAccountId": "firebase-adminsdk-xxxxxxx#[projectb].iam.gserviceaccount.com"
}, name="projectB")

How do I access Cloud Firestore when created as a service within Cloud Platform?

I'm familiar with using Cloud Firestore when created through Firebase, but I've created a Cloud Firestore as a service within Cloud Platform and I can't figure out how to have a client access that database. I was expecting there would be someway to generate a GoogleService-Info.plist so that my iOS app can access Firestore.
How is Cloud Firestore different when created from GCP, and how can clients access it?
If you want to access Firestore from iOS, you will still have to go through the Firebase console to add your app to the project and generate that plist file.
What you probably don't realize is that a Firebase project is just like a GCP project. Every Firebase project IS a GCP project, just pre-configured with some services and APIs enabled. Read this blog for a full discussion. If you created your project via the Cloud console, you can just as easily access the very same project from the Firebase console.
Your Firstore instance is 100% the same, no matter how you access it. All the same data and scaling behavior that you expect from Firestore. The only differences lie in how Firebase client apps add special mobile functionality. Read this blog for a full discussion specific to Firestore.
Bottom line is that, for use with mobile apps, you should still use the Firebase console to set that up. You can use both console together at the same time. They show almost entirely the same data, but Firebase is simplified for mobile-centric use.

Firebase Service Account for Firestore and Remote Config

I have created/forked a lil Google Apps Script Library to manage Firebase Firestore and Firebase Remote Config called FirebaseGoogleAppsScript. The goal is to simply manage the contents of your collections in an apps script as well as update your remote config.
My issue is I can't get the a service account to do both.
Firebase creates two service accounts upon creating a project:
The first is listed in the Firebase Console -> Project Settings -> Service Accounts. This one I use within my cloud functions to retrieve the Remote Config just fine. However in the Apps Script Project it is unable to retrieve any data from firestore. I tried adding all kinds of roles including Owner and Editor yet no firestore data, but I still can get the RemoteConfig.
The second is only visible in the GCP service accounts and has the title: Firebase Admin SDK Service Agent with the roles Firebase Admin SDK Administrator Service Agent and Service Account Token Creator. This one is able to retrieve all the data from firestore within an Apps Script Project. However in the apps script project I can't get it to retrieve the RemoteConfig even if I add the role Firebase Remote Config Admin.
I have also made my own service account which was able to get the Remote config and just about everything else from Firebase except the Firestore data. Seems only the one service account created by Firebase is able to get any data.
To recreate the issue simply deploy my lil FirebaseGoogleAppsScript project and associate it to the same GCP project Firebase is connected to. There is a test file in it which can recreate the issue assuming you have some data in RemoteConfig and a collection called posts with some docs.
What the heck is going on here? Why can't I make a service account who can access Firestore and RemoteConfig? Any ideas on what to do to create a proper role to do both? Do I really have to use two separate service accounts?

Resources