Search code examples
firebasegoogle-cloud-platformfirebase-cloud-messagingfirebase-admingoogle-cloud-iam

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..


Solution

  • 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.