I am developing a Flutter mobile app. From my Nodejs backend, I am trying to send FCM Notifications to the app. I downloaded the private key file from firebase console’s project settings. Below is my Nodejs code.
const errorCodes = require('source/error-codes'); const PropertiesReader = require('properties-reader'); const serviceAccount = require("service-account.json"); const fetch = require('node-fetch'); var { google } = require('googleapis'); var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging'; var SCOPES = [MESSAGING_SCOPE]; const prop = PropertiesReader('properties.properties'); exports.sendSingleNotification = async (event, context) => { const params = event.queryStringParameters; var PROJECT_ID = "xxxx-xxxx"; var HOST = "fcm.googleapis.com"; var PATH = "/v1/projects/" + PROJECT_ID + "/messages:send"; try { let promise = new Promise(function(resolve, reject) { var key = require("service-account.json"); var jwtClient = new google.auth.JWT( key.client_email, null, key.private_key, SCOPES, null ); jwtClient.authorize(function(err, tokens) { if (err) { reject(err); return { "error": "error 1" }; } resolve(tokens.access_token); }); }); let accessToken = await promise; // var options = { // hostname: HOST, // path: PATH, // method: 'POST', // headers: { // 'Authorization': 'Bearer ' + accessToken // } // // … plus the body of your notification or data message // }; var message = { "message": { "token": params.fcmtoken, "notification": { "title": "Portugal vs. Denmark", "body": "great match!" } } }; const response = await fetch('https://fcm.googleapis.com/v1/projects/' + PROJECT_ID + '/messages:send', { method: 'post', body: JSON.stringify(message), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accessToken } }); const data = await response.json(); // var request = https.request(options, function(resp) { // resp.setEncoding("utf8"); // resp.on("data", function(data) { // console.log("Message sent to Firebase for delivery, response:"); // console.log(data); // }); // }); // request.on("error", function(err) { // console.log("Unable to send message to Firebase"); // console.log(err); // }); // request.write(JSON.stringify(message)); // request.end(); return { "message": data } } catch (error) { console.log(error); return { "error 2": error } } };
Below is the content in my service-account.json
file
{ "type": "service_account", "project_id": "xxx-xxx", "private_key_id": "xxxxxxxxxxx", "private_key": "-----BEGIN PRIVATE KEY-----xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+xxxxx/xxxxx/xxxxxxxxxxxxx+xxxx/xxx+xxxxxxxx/lw/jiWVj6R6ZXYFtq0SloyRSQQufiPROEtQVZ/kYoxrQs5BZnt+9McW3Jtq5SMnYQIMUV1WdXOG+8a8ru2szOZmzLLaQr5RCGLUgdmGE2OP+04aSpnEMEu00DThQXYOLxUs5N2WOGfJ6Cpz9tfZR5fdBHbI0yJ/QEsFXKM5+gxsV23aFhjneAqWu4Gxr+lKV1h4ccpLk4O4teWcrcjLZS/h+xxxxx/AETt8mffnqy4PDZPsdYObjpPWM42VaaFv4wD2rjQigYN5SdglVhOjkihLAQM2+hhfO/gLA+UbnsD15Sp+xxxxxxxxxx/xxxxx+mpPDpISVtNngFEBqWYHhQYpQIpdAmQ7HhBLh5Gquf7w9OzdEZnfCeZGNzfeJ9NQJyefzqD9Ejspxxxxx+Og6vSGIrr9jUhkImxtayRIfZSAhufXP/gexqxxxxx+WVbeWjP8xt2Iule0hM3Qbtkppw9Dnxqxh+xxxxxn2PJyY43L+iv/fLG5unhOBT4oYL6pFEt/DzSAaI+xxxxxxxxx+xxxx/xxxx/xxxxxxxxx/UJDCGrxxxxx+Z5AoGBAJcLKoE0EaUVPN1BD7jgxxxxx+hnMGS0qWUw2AsYxeJXTLa7zWpkd9i8X5Evd5QlNm8BWaOjxxxx+xxxxxxxx/EJagS1n-----END PRIVATE KEY-----n", "client_email": "firebase-adminsdk-fguv2@xxx-xxx.xxx.gserviceaccount.com", "client_id": "xxxxxxxxxxxxxxxxxx", "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/xxx/firebase-adminsdk-fguv2%40xxx-xxx.iam.gserviceaccount.com" }
In my Flutter app, below is how I get the FCM Token.
String? token = await FirebaseMessaging.instance.getToken();
When I run my Node.JS code, I always end up with the following error. I am passing the FCM Token generated by the above flutter code.
{ "message": { "error": { "code": 400, "message": "The registration token is not a valid FCM registration token", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError", "errorCode": "INVALID_ARGUMENT" } ] } } }
If it helps, below is the accessToken
I get from the Node.js code. I am posting this because it looks weird to me anyways. The real code is converted into xxx
here but notice the lot of dots (.) available in the authentication token!
xxx.c.xxx-G0WwTjZbMZQ1Bh0xxxxxxxxxxx_o5wl4U1A7cIJN3t87k10DqyEo4Wu1CJu_vFrva0-S9nkwxlVmG3AAjxfYIyVFsszcbrcF-xxxxxx........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Why is this happening and How to fix this issue? FYI I tried the firebase admin-sdk
for Nodejs and the result is same as this.
Advertisement
Answer
I found the issue myself and wanted to share it for the benefit of others.
The important thing is that my code is correct, nothing wrong with it. However I was trying to execute this as a get
function and I have passed the FCM Token as a parameter. This didnt work because the parameters contains a max length limit. As a result, my parameter got truncated when sending to the server.
All what I had to do is convert this call to a post
and send the FCM Token in the body
.