4

The goal is to make my express server send a push notification using Firebase Cloud Messaging (FCM).

The problem is that the initialization of the admin SDK does not seem to work. Code is written in JavaScript, node version is 10.16.0, firebase-admin is version 8.3.0, Server is running on latest Ubuntu.

I followed the firebase guide to set up the admin SDK: https://firebase.google.com/docs/admin/setup#initialize_the_sdk

The GOOGLE_APPLICATION_CREDENTIALS environmental variable is set, and trying to open the file using the variable works:

nano $GOOGLE_APPLICATION_CREDENTIALS

Once

admin.messaging().send(message)

is called, the following error is thrown:

Error sending message: { Error: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal metadata.google.internal:80. Error code: ENOTFOUND".
    at FirebaseAppError.FirebaseError [as constructor] (/local/home/user/node_modules/firebase-admin/lib/utils/error.js:42:28)
    at FirebaseAppError.PrefixedFirebaseError [as constructor] (/local/home/user/node_modules/firebase-admin/lib/utils/error.js:88:28)
    at new FirebaseAppError (/local/home/user/node_modules/firebase-admin/lib/utils/error.js:122:28)
    at /local/home/user/node_modules/firebase-admin/lib/firebase-app.js:121:23
    at process._tickCallback (internal/process/next_tick.js:68:7)
  errorInfo:
   { code: 'app/invalid-credential',
     message:
      'Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal metadata.google.internal:80. Error code: ENOTFOUND".' },
  codePrefix: 'app' }

The implementation follows the firebase guide very closely.

Similar problems point towards the spark plan not supporting cloud functions. But to my understanding, I am trying to use Cloud messaging and not cloud functions.

I don't have a clue what is wrong. Especially since it is very similar to the code from the guide. Do I need to install some other firebase components other than the firebase-admin?

Server code:


const express = require('express');


//firebase for notifications
const admin = require('firebase-admin');


admin.initializeApp({
    projectId: <projectId>,
    credential: admin.credential.applicationDefault(),
    databaseURL: "https://<projectId>.firebaseio.com"
});

// server set up removed


io.on('connection', socket => {

    socket.on('notification', (target, message) => {
        // This log is printed
        console.log("got notification for: ", target)
        // target = registration token comes from the client FCM SDKs.
        if (typeof (target) === "string") {
            sendNotifiaction(target, message)
        }
    });

});

function sendNotifiaction(registrationToken, message) {
    // This registration token comes from the client FCM SDKs.
    message.token = registrationToken

    // Send a message to the device corresponding to the provided
    // registration token.
    admin.messaging().send(message)
        .then((response) => {
            // Response is a message ID string.
            console.log('Successfully sent message:', response);
        })
        .catch((error) => {
            // Error catched here
            console.log('Error sending message:', error);
        });
}

Service Account Key (path to file = $GOOGLE_APPLICATION_CREDENTIALS). Some field obviously omitted.

{
  "type": "service_account",
  "project_id": "..",
  "private_key_id": "..",
  "private_key": "-----BEGIN PRIVATE KEY-----.."
  "client_email": "firebase-adminsdk-.....iam.gserviceaccount.com",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-......iam.gserviceaccount.com"
}
Noah Studach
  • 405
  • 4
  • 14
  • what exactly r u setting as a credential? – andresmijares Jul 27 '19 at 14:00
  • @andresmijares I use a service account key that I got from firebase console -> settings -> Service Accounts -> Generate new private key. I followed [this guide](https://firebase.google.com/docs/admin/setup#initialize_the_sdk) – Noah Studach Jul 28 '19 at 11:00
  • 1
    everything seems correct to me, just for the sake of debugging, what happens if you try to log the env variable before the admin.initializeApp line? take a look if the variable is accessible into your app – andresmijares Jul 28 '19 at 13:35
  • thank you. It seems the issue was with not finding the file. I hardcoded the location and it worked. (I tried it this way before with no success, maybe I had a typo...). However thanks again for the help. – Noah Studach Jul 30 '19 at 13:18

2 Answers2

3

Solution

I just used the code sample provided by firebase console (Settings->Service Accounts).

Note: I tried this before and it did not work: So check that the path is correct and your server has permission to access it.

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://<ProjectId>.firebaseio.com"
});
Noah Studach
  • 405
  • 4
  • 14
  • 1
    I had to export the credentials using `GOOGLE_APPLICATION_CREDENTIALS` to get it to work but in my case I am using the emulator command `firebase functions:shell` – George Udosen Dec 25 '19 at 06:43
  • 2
    This does work for me, however, I wonder what's a good way to (1) store that key, (2) switch this code based on dev vs. prod environment. – Zorayr Jun 01 '20 at 19:17
  • @Zorayr im trying to figure that out as well, been spending way too much time on this :/ – corasan Aug 13 '20 at 21:13
  • @Zorayr I actually figured it out, I think. Here is a link to a gist with what I ended up doing and works for me: https://gist.github.com/corasan/330bfd5549dc25eaa694b8ea39fca960 – corasan Aug 13 '20 at 21:56
0
  • Step1: Go to your firebase console.
  • Step2: go to your project.
  • Step3: In project go to project settings -> service accounts

and click on Generate new private key.

var admin = require("firebase-admin");

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount)
});

Go to your code paste the above code and give your serviceKey.json file path and your app will be initilized.

ANOOP NAYAK
  • 473
  • 5
  • 8