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.