Why is Twilio push notifications not working? - javascript

I am working on a Next.js project and I included the twilio chat. The next step I want to do is to set up the push notifications. I tried to follow this guide and it seems all to be fine. I actually get the FCM token and pass it to the twilio chat SDK. I expect that when I write a message something happens even errors, but I see nothing.
I have the following code:
messaging_get_token.js
import { initializeApp } from 'firebase/app';
import { getAnalytics } from 'firebase/analytics';
import { getMessaging, getToken, onMessage } from 'firebase/messaging';
export const firebaseConfiguration = () => {
const firebaseConfig = {
apiKey: 'my api key',
authDomain: 'my auth domani',
projectId: 'my project id',
storageBucket: 'my storage bucket',
messagingSenderId: 'my messaging sender id',
appId: 'my app id',
measurementId: 'measurement id',
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
};
export const handleNotifications = async (chatClientInstance) => {
firebaseConfiguration();
const messaging = getMessaging();
getToken(messaging, {
vapidKey: 'my vapid key'
})
.then((currentToken) => {
if (currentToken) {
// the flow arrives here and I get no errors
chatClientInstance?.client.setPushRegistrationId('fcm', currentToken);
onMessage((payload) => {
chatClientInstance?.client.handlePushNotification(payload);
});
} else {
console.log(
'No registration token available. Request permission to generate one.'
);
}
})
.catch((err) => {
console.log('An error occurred while retrieving token. ', err);
});
};
After this I call the function handleNotifications(client) in a useEffect when I render the chat component and pass to it the twilio Client.
In order to get the twilio client and channel I did this:
import toast from 'react-hot-toast';
const Chat = require('twilio-chat');
export const getTwilioClient = async (token: string, room?: string) => {
const client = await Chat.Client.create(token || 'no_token');
let channel;
const joinChannel = async (channel) => {
if (channel.channelState.status !== 'joined') {
await channel.join();
}
};
if (room) {
try {
channel = await client.getChannelByUniqueName(room);
await joinChannel(channel);
} catch {
try {
channel = await client.createChannel({
uniqueName: room,
friendlyName: room,
});
await joinChannel(channel);
} catch {
toast.error('Unable to create channel, please reload this page');
throw new Error('unable to create channel, please reload this page');
}
}
}
return { client, channel };
};
I followed all the steps, but I can't figure out why I don't see anything. Is there something I missed? Unfortunately I don't find any sample about doing this..
p.s.
I use twilio 3.71.3, twilio-chat 6.0.0 and firebase 9.6.8

Related

Firebase auth google provider popup (and redirect) gives blank page

I have been trying to set up firebase auth for my next js project, and while it works to sign in and login with email og password, google sign in does not, it opens popup (or redirects if use signInWithRedirect()) but the popup is empty. Does not show my google accounts. Just loads an empty screen from 'https://project.firebaseapp.com/__/auth/handler?apiKey=blablabla&appName=%5BDEFAULT%5D&authType=signInViaPopup&redirectUrl=http%3A%2F%2Flocalhost%3A3000%2Flogin&v=9.16.0&providerId=google.com&scopes=profile'
A weird part is that it worked for a short while earlier, but then at some point it stopped, and I don't now what I changed, if I changed anything at all. Tried resetting back to old code, and also setting up new firebase project, but does not work anymore.
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
export const firebaseConfig = {
apiKey: "blabla",
authDomain: "project.firebaseapp.com",
projectId: "project",
storageBucket: "project.appspot.com",
messagingSenderId: "blabla",
appId: "blabla",
measurementId: "blabla"
}
// Use this to initialize the firebase App
export const firebaseClient = !firebase.apps.length
? firebase.initializeApp(firebaseConfig)
: firebase.app();
// Use these for db & auth
export const db = firebaseClient.firestore()
export const auth = firebaseClient.auth()
export const googleProvider = new firebase.auth.GoogleAuthProvider()
export default firebaseClient
this is signin functions (with mail & password works):
function signIn(e: React.MouseEvent<HTMLElement>) {
e.preventDefault()
if (emailRef.current && passwordRef.current) {
auth.signInWithEmailAndPassword(
emailRef.current.value,
passwordRef.current.value
).then((authUser) => {
console.log(authUser)
router.push('/dashboard/profile')
})
.catch((error) => {
alert(error.message)
})
console.log("signin", emailRef.current.value, passwordRef.current.value)
}
}
function signInGoogle(e: React.MouseEvent<HTMLElement>) {
e.preventDefault()
auth.signInWithRedirect(googleProvider)
.then((authUser) => {
console.log(authUser)
router.push('/dashboard')
})
.catch((error) => {
alert(error.message)
})
}
EDIT:
Here is some more info:
The only errors I get are these cookie issues:
I also however get another error when connecting to my firestore, which maybe is correlated??
this is the code for that (which logs no products...):
useEffect(()=>{
db.collection('products').where('active','==', true).get()
.then((querySnapshot) => {
querySnapshot.forEach(async (product) => {
console.log(product.data);
})
})
.catch((error) => {
alert(error.message)
})
}, [])

Twilio Conversations push notifications with Firebase Cloud Messaging

I'm attempting to set up push notifications using Twilio Conversations and Firebase Cloud Messaging on a Next.js 12 app. The documentation is written with the assumption of using Firebase 8 syntax, but I'm using Firebase 9 in this scenario. I've been struggling to get push notifications to work while the page is open. I have the service worker set up (per Firebase docs) but it doesn't seem to be recognizing that a new message is being received from Twilio in order to actually show the notification.
Docs I've followed:
https://www.twilio.com/docs/conversations/javascript/push-notifications-web
https://firebase.google.com/docs/cloud-messaging/js/client
What I've tried
On my backend, I pass the Push Credential SID when I construct a new ChatGrant:
const chatGrant = new ChatGrant({
pushCredentialSid: process.env.TWILIO_PUSH_CREDENTIAL_SID,
serviceSid: CONVERSATIONS_SID
});
In the frontend, I followed the Twilio documentation to set up Firebase:
init.ts
import { getMessaging, getToken, onMessage } from "firebase/messaging";
import { initializeApp } from "firebase/app";
import { Client } from "#twilio/conversations";
// Omitted
const firebaseConfig = {};
export function getPermission(client: Client) {
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
getToken(messaging, { vapidKey:"KEY" })
.then((data) => {
console.log({ data });
client.setPushRegistrationId("fcm", data).catch((error) => {
console.error({ error });
});
onMessage(messaging, (payload) => {
console.log({ payload });
client.handlePushNotification(payload).catch((error) => {
console.error(error);
// test
});
});
})
.catch((error) => {
console.error(error);
// test
});
}
I call getPermission from this file once when the conversation app loads.
// chatClient is stored in a ref so it doesn't recalculate/refetch/reauthorize all the time
const chatClient = useRef(null);
// [Other code]
chatClient.current = new ConversationClient(data.chatAccessToken);
chatClient.current.on("connectionStateChanged", async (state) => {
switch (state) {
case "connected": {
// Only get permission once the chat client is fully set up
getPermission(chatClient.current);
// ..........
And my service worker firebase-messaging-sw.js:
importScripts('https://www.gstatic.com/firebasejs/9.14.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.14.0/firebase-messaging-compat.js');
if (!firebase.apps.length) {
firebase.initializeApp({
// CONFIG GOES HERE
});
}
const messaging = firebase.messaging();
//background notifications will be received here
messaging.onBackgroundMessage(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/android-chrome-192x192.png'
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
What's happening
In the service worker, messaging.onBackgroundMessage never appears to be invoked. I don't know where this issue is derived from - is Twilio not passing message info to Firebase? Or is Firebase not listening to when Twilio sends it the information? Has that changed from v8 to v9?
In init.ts, onMessage is never invoked. Same deal here, is Twilio not passing the right information to Firebase, or did I misconfigure something?
I'm not getting any console errors or warnings, and the network tab is not pointing out anything super helpful.
I got this to work by using the example code (from docs) and configuring my Next.js application to compile the TypeScript into JavaScript. This helped a lot: https://github.com/vercel/next.js/issues/33863#issuecomment-1140518693

How to log out from both server side and client side on a SSR Nuxt.js application using Firebase authentication?

As the title suggests, in my Nuxt webapp using Firebase auth in SSR mode, I want to have the following behaviour :
As a client, by clicking on logout button from my profile space, I want to keep this state even if I reload the page.
But for the moment it seems to be that I'm only log-out from the client side (by clearing cookies, vuex store) but on server side User data/session looks still alive, then on page refresh with F5 the vuex store is set-up again, even if we add 'gates' to prevent it ! (check cookies from req object, get local user from res object).
I think something is missing in my config, so can someone tell me what is it ?
=> Here the nuxt.config.js file :
// ...
firebase: {
config: {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: `${process.env.FIREBASE_PROJECT_ID}.firebaseapp.com`,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: `${process.env.FIREBASE_PROJECT_ID}.appspot.com`,
messagingSenderId: process.env.FIREBASE_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
},
services: {
auth:
{
ssr: true
},
firestore: true
}
},
// ...
pwa: {
manifest: {
// ...
},
workbox: {
importScripts: ['firebase-auth-sw.js'],
dev: process.env.ENV === 'development', // Must be FALSE for prod env.
},
},
// ...
=> The index.js store :
import { vuexfireMutations } from 'vuexfire';
import cookieparser from 'cookieparser';
export const mutations = {
// Plugin used for Firestore operations (read, write)
...vuexfireMutations,
};
export const actions = {
async nuxtServerInit({ dispatch }, { req, res }) {
if (process.server && process.static) return;
if (!req?.headers?.cookie) return;
const { token: currToken } = cookieparser.parse(req.headers.cookie);
if (!currToken) return;
if (!res?.locals?.user) return;
const { allClaims: claims, idToken: token, ...authUser } = res.locals.user
console.info('Auth User verified on server-side. User: ', authUser, 'Claims:', claims)
dispatch('onAuthStateChanged', { authUser, claims, token })
},
onAuthStateChanged({ commit }, { authUser, claims, token }) {
console.log('authUser :', authUser);
if (!authUser) {
commit('user/resetState');
return;
}
// Set existing user into vuex store
const existingUser = {
uid: authUser.uid,
email: authUser.email,
token: token,
}
commit('user/setUser', existingUser);
},
};
=> The log-out method from store/user.js :
async logOut({ commit }) {
try {
await this.$fire.auth.signOut();
commit('resetState');
this.$cookies.removeAll()
} catch (error) {
console.error('Error on logout process from client side :', error);
throw error;
}
},
To be more precise, on page refresh, the user data is set again without calling the commit('user/setUser', existingUser); line ! Don't know how and why...
Thanks in advance for any help ! :)

NodeJS: Firebase Admin SDK is not initializing

I am trying to run the below cod which initialises the Firebase Admin SDK, and send a notification message.
const admin = require('firebase-admin/app');
const errorCodes = require('source/error-codes');
const PropertiesReader = require('properties-reader');
const prop = PropertiesReader('properties.properties');
exports.sendSingleNotification = async (event, context) => {
const params = event.queryStringParameters;
var serviceAccount = require("xxx-xxx-firebase-adminsdk-xxx-xxx.json");
try {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
console.log("INITIALIZED");
// This registration token comes from the client FCM SDKs.
const registrationToken = params.fcmtoken;
console.log()
const message = {
notification: {
title: 'FooCorp up 1.43% on the day',
body: 'FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
token: registrationToken
};
// Send a message to the device corresponding to the provided
// registration token.
admin.getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
return {"response":response}
})
.catch((error) => {
console.log('Error sending message:', error);
return {"error 1":error}
});
} catch (error) {
console.log(error);
return {"error 2":error}
}
};
Here the serviceAccount means the path of the Firebase private key file which is in the root of this project.
However when I run this code I always end up with the following error.
START RequestId: e66ffdd9-ab9c-4a68-ade2-7cfa97f42c31 Version: $LATEST
at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)] (/var/task/source/fcm/send-single-notification.js:14:42)rt' of undefined
END RequestId: e66ffdd9-ab9c-4a68-ade2-7cfa97f42c31
Something is undefined and I can't figure out what it is or what the error is.
How can I fix this?

Recaptcha is working, Email is Verified, 2FA turned on in console... yet auth/internal-error when running .verifyPhoneNumber()

I have checked other StackOverflow posts and haven't seen anything that addresses the issue. I am trying to set up multi-factor auth for my app. As far as I've understood the basic steps are:
Enable 2FA in firebase console & Google Cloud Console ✔️
Set up a reCaptcha ✔️
Get the session ✔️
And send a verification message with phoneAuthProvider.verifyPhoneNumber ❌
I'm not sure why as all I am getting is FirebaseError: Firebase: Error (auth/internal-error)
Imports
import 'firebase/auth';
import * as firebase2 from 'firebase/auth';
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import firebaseApp from '../../../../src/config';
import { getAuth } from 'firebase/auth';
Here is the recaptcha:
useEffect(() => {
try {
const auth22 = getAuth();
// Recaptcha only ran once, stored in state
const recaptchaVerifier = new firebase2.RecaptchaVerifier(
'multifactor-form',
{
size: 'invisible',
callback: (response) => {
console.log('successfully created the captcha');
console.log(response);
},
},
auth22
);
console.log(recaptchaVerifier);
setCaptchaVerifier(recaptchaVerifier);
} catch (e) {
console.log(e);
}
}, []);
And here's the function I run when I click send SMS:
const sendSMS = async function (phoneNumber: any) {
console.log(phoneNumber);
console.log(typeof phoneNumber);
try {
let verificationId: any;
const auth = firebaseApp.auth();
const user = auth.currentUser;
const newNumber: string = `+1${phoneNumber}`;
const session = await user.multiFactor.getSession();
const phoneOpts = {
newNumber,
session,
};
const phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
verificationId = await phoneAuthProvider.verifyPhoneNumber(phoneOpts, recaptchaVerfifier);
//Nothing runs after the line above this one
alert('sms text sent!');
} catch (e) {
console.log(e);
}
};
Can anyone see anything wrong with what I'm doing?
If needed Here are the tutorials, and guides, I've been following along with:
https://fireship.io/lessons/two-factor-auth-firebase/#identity-platform
https://cloud.google.com/identity-platform/docs/web/mfa?_ga=2.210928085.-1381314988.1638978774
I had the same error. Some info in docs is incorrect https://cloud.google.com/identity-platform/docs/web/mfa#web-version-8_21
Incorrect !!!
// Specify the phone number and pass the MFA session.
var phoneInfoOptions = {
phoneNumber: phoneNumber,
session: resolver.session
};
Correct version is in the complete example code at the bottom of docs:
var phoneInfoOptions = {
multiFactorHint: resolver.hints[selectedIndex],
session: resolver.session
};

Categories