Firebase Service Account for Firestore and Remote Config - firebase

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?

Related

How to access a Firebase project

An app developer has written some code for me that is hosted on Firebase. I want access to the code and so they have apparently given me admin access.
It's a simple question, but I can't figure out how to access the project. I log into the console:
I see how to "create a project", but I don't know how I can access an existing project. I'm assuming thinking about this whole thing in the wrong way somehow. I would appreciate any help.
You typically have two types of administrators in an app built on Firebase:
Project/Firebase administrators who access the project in the Firebase console, and can access the backend view of the services there. This is typically used by the developers on the project, and early administrators. To access the Firebase console, you will sign in with a Google account on console.firebase.google.com.
Application administrators, who use a custom-built interface to manage typical application operations, such as giving roles to users, upgrading accounts, etc. For this type of functionality, you will sign in to the custom built application with a Firebase Authentication account.
The email you got came from Firebase Authentication for an account that was created inside the project. There is no way for this account to be a Firebase administrator or even collaborator on the project, so it was more likely meant as an application administrator. This means that any functionality this allows you to access will have to have been built as part of the app itself, and not in the Firebase console.
updaterequest(messagemap) async {
await FirebaseFirestore.instance
.collection("mentor")
.doc("request")
.update(messagemap)
.catchError((e) {
print(e.toString());
});
}
This is a code used to update some value in your firebase collections. You can use get instead of update to retrieve data from firebase collection. There is also some function like add,remove,set it can be used instead of update command.

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.

Difference between Firebase service account key files from Firebase and from GCloud?

I am running scripts to interact with Firestore (e.g. creating a doc). I've provided a service account key file to do so (tried with key files from Firebase and GCloud) - scripts run the same.
I am aware that Firebase is now built / closely linked to GCloud so I am expecting the key files to be similar.
However, the docs recommend initializing the sdk with a key from Firebase console when adding Firebase admin to your server and from GCloud Console for unit testing.
So here are my questions:
Why recommend 2 different ways to generate them? Is one more appropriate than the other?
Do service account key files generated in Firebase (1) and GCloud (2) consoles differ in terms of scope? Do they allow the same operations? Are they granted equivalent permissions?
Firebase Console > Project Settings > Service Accounts > Firebase Admin SDK > Create new private key
https://console.firebase.google.com/project/[my-project-id]/settings/serviceaccounts/adminsdk
Google Cloud Console > IAM & Admin > Service Accounts > App Engine default service account > Create key
https://console.cloud.google.com/iam-admin/serviceaccounts?project=[my-project-id]
The service account and credentials provided by the Firebase console are no different than one that you'd create in the Cloud console. Firebase is just making it easier to get started, so you don't have to learn the Cloud console. If you want to use the one provided by Firebase, fine. If you want to use one you create and configure in the Cloud console, fine. The Firebase service account should be visible in the Cloud console just like any other. When it comes to assigning permissions to individual products, you can still choose either one to work with. It's up to you.

How to configure Flutter apps to share Cloud Firestore

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?

Does firebase login:ci have access to all my projects?

I am using the firebase login:ci token for CI/CD. But there is not enough documentation regarding the token.
Does it have access to all my firebase projects where my account has access or only the current active project?
Where can I see a list of all tokens and their activity?
The solution I am going for is creating a throwaway email and adding that to the project I want to deploy. Is this ok?
When you run firebase login:ci you get prompted to log in with a Firebase account. After picking your account, you get a dialog that shows the permissions you're granting. This contains:
This will allow Firebase CLI to:
View and administer all your Firebase data and settings
So if you click Allow in that dialog, the Firebase CLI will have access to all Firebase projects that the account has access to. The generated token does (as far as I know) have access to the same scope.

Resources