node js FCM Send notifications to multiple users at once - node.js

I am building cloud notifications based on Firebase. We are currently working on creating a server as node js and controlling cloud notifications.
However, I have searched a lot of data, and most of the above data is transmitted to only one person by receiving the token value when sending notifications.
Of course, i can use mysql to send it to a large number of people, but is it possible to send it to all users who have the app installed as a user segment like the Firebase console?
Here is the site I referenced. I made it using the script provided here.
https://www.npmjs.com/package/fcm-node

but is it possible to send it to all users who have the app installed as a user segment like the Firebase console?
Not possible out of box. You need a user's registration token to do any sort of messaging. If you do not have all your user's registration tokens, then you'll need to retrieve it for each user. Remember to verify the tokens before persisting them to your database: https://firebase.google.com/docs/auth/admin/verify-id-tokens
And as the readme states for fcm-node:
Warning: on February 2, 2017, the Firebase Team released the admin.messaging() service to their node.js admin module. This new service makes this module kind of deprecated
With that said, you have two options:
Send notifications to multiple users via their registration token:
-
const registrationTokens = [
'abc',
'efg',
'123'
];
const message = {
data: {
score: '850'
},
token: registrationToken
};
const promises = [];
registrationTokens.forEach(token => {
const promise = admin.messaging().send(message);
promises.push(promise);
});
Promise.all(promises)
.then(results => console.log(results))
.catch(err => console.error(err));
Or better yet, use Topic Messaging on a "user segment". You'll need to subscribe users to their respective topic. For example, Android documentation on how to do that can be found here
-
const message = {
data: {
score: '850'
},
topic: 'myUserSegmentTopic'
};
admin.messaging().send(message)
.then(res => console.log(res))
.error(err => console.error(err));

Related

is it possible to send push notification to only active clients using firebase cloud messaging and node.js server

I want to know wether it is possible to send push notification using firebase cloud messaging and node.js server? How can I do this?
Yes, It is possible using either API endpoints provided by firebase or by using firebase-admin npm package.
Minimal Example -
const firebaseAdmin = require('firebase-admin')
if (!firebaseAdmin.apps.length) {
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccountJson),
databaseURL: databaseUrl
})
}
// This registration token comes from the client FCM SDKs.
const registrationToken = 'YOUR_REGISTRATION_TOKEN';
const message = {
data: {
score: '850',
time: '2:45'
},
token: registrationToken
};
// Send a message to the device corresponding to the provided
// registration token.
firebaseAdmin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
For further documentation please refer to -
https://firebase.google.com/docs/cloud-messaging/send-message

How to send email verification when registering a new user in Firebase? [duplicate]

In the past, I have used firebase.auth in the web client and once a user creates another user, I link certain security logic:
Once the user has been created I send an email to verify your email
with the function user.sendEmailVerification ().
As the user was created by another user, I assign a default password
and use the sendPasswordResetEmail () function so that the user
registers his new password.
That has worked well for me so far, but now for many reasons I need to move that logic to my server, for that I'm developing a backend with cloud functions and I'm using the Node.js Firebase Admin SDK version 6.4.0, but I can not find a way to use the functions of user.sendEmailVerification() and sendPasswordResetEmail() to implement the same logic on the server, the closest thing I found was:
auth.generateEmailVerificationLink (email)
auth.generatePasswordResetLink (email)
But it only generates a link for each one, which by the way the only emailVerification() serves me, the one from generatePasswordReset always tells me:
Try resetting your password again
Your request to reset your password has expired or the link has
already been used.
Even though be a new link, and it has not been used.
My 3 questions would be:
How can I make the sendEmailVerification () and
sendPasswordResetEmail () functions work on the server?
How can I make the link generated with
auth.generatePasswordResetLink (email) work correctly on the server?
Is there any way to use templates and emails on the server that are
in firebase auth?
Thank you in advance for sharing your experience with me, with all the programmers' community of stack overflow.
Those functions are not available in firebase-admin, but you should be able to run the client-side SDK (firebase) on the server as well. Not exactly a best practice, but it will get the job done. There's a long standing open feature request to support this functionality in the Admin SDK. You will find some helpful tips and workarounds there.
Could be a bug. I would consider reporting it along with a complete and minimal repro. The Admin SDK does have an integration test case for this use case, but it works slightly differently.
Not at the moment. Hopefully, this will be covered when the above feature request is eventually fulfilled.
The is a workaround provided here
https://github.com/firebase/firebase-admin-node/issues/46
I found a work-around that works well enough for my use case, see below. I'm not sure if this is best practice, but I wanted to keep the emails exactly the same between the server and client requests. Would love to hear about any flaws with this implementation 💡
As suggested above, it uses a three step process to do this:
Acquire a custom token via the admin sdk's createCustomToken(uid)
It converts this custom token to an idToken via the API
It invokes the send email verification endpoint on the API
const functions = require('firebase-functions');
const fetch = require('node-fetch');
const admin = require('firebase-admin');
const apikey = functions.config().project.apikey;
const exchangeCustomTokenEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${apikey}`;
const sendEmailVerificationEndpoint = `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${apikey}`;
module.exports = functions.auth.user().onCreate(async (user) => {
if (!user.emailVerified) {
try {
const customToken = await admin.auth().createCustomToken(user.uid);
const { idToken } = await fetch(exchangeCustomTokenEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: customToken,
returnSecureToken: true,
}),
}).then((res) => res.json());
const response = await fetch(sendEmailVerificationEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
requestType: 'VERIFY_EMAIL',
idToken: idToken,
}),
}).then((res) => res.json());
// eslint-disable-next-line no-console
console.log(`Sent email verification to ${response.email}`);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
});
I'm sure it doesn't matter anymore, but I had a headache doing this so I'd like to share even if it isn't the greatest answer.
await admin.auth().createUser(
{email, password, displayName, phoneNumber, photoURL}
).then(function(userRecord) {
admin.auth().createCustomToken(userRecord.uid).then(function(customToken){
createdToken=customToken;
firebase.auth().signInWithCustomToken(createdToken).catch(function(error){
return console.log(error)
})
firebase.auth().onAuthStateChanged(function(user) {
user.sendEmailVerification().then(function(){
return console.log('It worked')
},function(error) {
return console.log(error)
})
});
})
})

Firebase web push notification with NodeJS not working

I'm building an app that sends web push notifications using firebase and a NodeJs server but I'm getting a 'mismatched-credential' error, how can I fix this?
I'm first generating a json file that 'generate private key' button from the console gave me , and adding the admin SDK to my app, from my server code, this way
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://nodeproject-2bc3o.firebaseio.com"
});
Then I'm building the send request
// This registration token comes from the client FCM SDKs.
var registrationToken = 'YOUR_REGISTRATION_TOKEN';
var message = {
data: {
score: '850',
time: '2:45'
},
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) => {
console.log('Error sending message:', error);
});
The docs says that // This registration token comes from the client FCM SDKs so I'm using the token I got from the client as my registrationToken, which I retrieved the following way , from my client javascript code , and then sent to the server
messaging.getToken().then((currentToken) => {
if (currentToken) {
sendTokenToServer(currentToken);
updateUIForPushEnabled(currentToken);
}
Finally, after sending a message from the server, using the token , I get the following error
errorInfo: {
code: 'messaging/mismatched-credential',
message: 'SenderId mismatch'
},
codePrefix: 'messaging'
}
Which is the correct way to retrieve the client token , send it to the server , and then use it to send a push notification to the client? Or what I'm I doing wrong?
If you use Firebase Cloud Functions as backend server then the serviceAccountKey.json is not necessary and more simple.
See https://firebase.google.com/docs/functions/get-started#import-the-required-modules-and-initialize-an-app
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
These lines load the firebase-functions and firebase-admin modules, and initialize an admin app instance from which Cloud Firestore changes can be made.
And, fcm sample is https://github.com/firebase/functions-samples/tree/master/fcm-notifications

Is there a way to identificate connected users while they chat with bot?

So im new to IBM Watson assistant, and i am wondering, when i initialize session for a current usern who sent message, where should i store it, and how can i tell watson to make difference between session_id's of user1 and user2 for example?
Right now i tried using a global variable in nodejs, but as i said in that way i could not make a difference between sessions of multiple users.
const assistant = new WatsonAssistant({
username: process.env.WATSON_USERNAME,
password: process.env.WATSON_PASSWORD,
url: process.env.WATSON_URL,
version: process.env.WATSON_VERSION
});
exports.getMessage = body => new Promise(async (resolve, reject) => {
// Initializing session for current user
if(!global.session_id){
const createdSessionId = await assistant.createSession({
assistant_id: process.env.WATSON_ASSISTANT_ID
});
global.session_id = createdSessionId.session_id;
}
assistant.message(
{
workspace_id: process.env.WATSON_WORKSPACE_ID,
input: { text: body.input },
session_id: global.session_id,
assistant_id: process.env.WATSON_ASSISTANT_ID
},
function(err, response) {
if (err) {
console.log(err);
reject(err);
} else {
resolve(response);
}
}
);
});```
I would like to have session_id's of multiple users who have used my chatbot.
I would recommend using NodeJS Express as your web server, and then some Express session middleware to manage the user session (between the web browser and the server). An middleware I have used is "express-session".
For example I would do this:
const session = require('express-session');
// use unique value for secret, here using the bot workspace ID
app.use(session({secret: process.env.WORKSPACE_ID}));
You then have a "req.session" object you can store data on and retrieve in subsequent calls by the same user. You could store your Assistant session ID on this req.session object so that it is available. A different user will get a different express session and thus a different Assistant session.
The default implementation of "express-session" uses memory so as per their README you will want to use something such as disk or database for production purposes.

Not getting email

I am using google sign in on my app and I am using ionic v3 and the native google plugin so the user is directed to google to sign in and allow us access. Once the user allows access and I send the request to my backend where i use the userId sent from Google to get the users info. I get all the info I need except for the email address. Not sure why the users email is not showing up. Here is my backend code:
const plus = googleAPI.google.plus({
version: 'v1',
auth: 'My API Key'
});
plus.people.get({
userId: googleUserId,
fields: 'displayName,emails,name'
})
.then((user) => {
console.log('Google plus user: ' + JSON.stringify(user.data));
console.log('Emails: ' + user.data.emails)
})
.catch((err) => {
console.log('Google plus error: ' + err);
})
Seems like its a permissions issue because on the app I set a iOS webClientId which is different than my API key. If so how do I go about fixing it?
Figured it out the api call was missing the accessToken as part of the get

Resources