STOP Push notification after logout - push-notification

I'm using angular in my project which user swPush. The notification works fine, but even after user1 logged out am getting the push notification. I don't want to push notification to the logged out users.After the user2 logged in both user1 and user2 getting notifications on the same device, this confuses the user. I want to restrict the user to get notification only when they logged in. How can I do achieve this. Is there any method.
I already try unregistering the service workers using
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister()
}
})
But after using this, both the users are not getting notification.
Thanks and regards

You should not unregister the Service Worker registrations because, well, that unregisters all of them. Unregistering Service Worker prevents any push logic from happening since web push is a layer on top of Service Workers - you need to have Service Workers registered and active in order to use push notifications, right?
You have two options if you only think about "showing the notifications":
When the user logs out, stop sending the push notifications. Of course this means that the web app logic has to inform your server somehow that now the logout event happened and precisely who it was (which of the possible different browser sessions of this particular user). Of course your server should already have information about the logout event.
Keep track of the logged in user in the browser (your JS code) and only show push notifications relevant to that user. You need to somehow distinquish between the receivers of the push notifications and the active user sessions in the browser and most likely handle it in self.addEventlistener('push', ...) in the SW.
If you think about privacy/security standpoint, the option #2 is of course wrong. If you only hide/not show the logged-out user's notifications, it means you're still sending them from the server. The notifications could include private information and whatnot.
So really you should go for #1. That's the right way to implement this. It leaks no information from the logged-out users, keeps the users' push subscriptions separate, and saves bandwidth.

Related

how t check if notifications are allowed with FCM without triggering a permission prompt

I want to know if the user has allowed notifications on the current browser so I can show that state on the UI, but I don't want to trigger the request permission unless the user performs an action to enable notifications.
This is kind of a chicken egg problem because I don't have a reliable way to identify the current user browser.
I can store the FCM token on the firebase database and fetch it on the FE. But each token is unique for each browser and I can not compare it to anything, the only way I have to check if one of the existing tokens is for the current browser is to use the getToken method from firebase FCM and check the returned token is on the list of tokens, but that may trigger a request permission prompt and I don't want that unless the user asks for it.
One possible solution may involve storing a flag on local storage, but if the user clears it the UI will show notifications as disabled when the user is still subscribed to the FCM topic. I know the Notification API has a property that indicates if the user has granted notification permissions but that may have happened and the token not retrieved for some random network error, so I can not rely on this solely. Also it only indicates if the user has granted permissions, but on my application logic notifications may be disabled (because user choice) and that does not revokes the permissions.
Things are also not nice if user wants to disable notifications: in order to delete the token from the database, I need the current browser token, and the only reliable way to know the current browser token is to ask it with getToken which may trigger a request permission if the user has disabled notifications and I will never get the actual token and I need it to remove it from the database
Are there any guidelines about how to deal with this? The FCM docs are quite sparse
This is a solution that I'm not sure if it is super robust, but it's simple and probably to meet most cases.
First, check if the current browser has notifications allowed. If not, just show that value on the UI because the user will not get the notifications anyway even if they are subscribed on the backend side.
If notifications are already allowed you can safely run getToken (will not trigger permission request) and compare the value against the values on the user/profile database.
Because I'm using react here is an implementation on a hook:
const areNotificationsAllowed =
Notification && Notification.permission === "granted";
useEffect(() => {
// because we don't want to trigger a permission request
if (!areNotificationsAllowed) return;
// Notifications are allowed, we can safely run getToken to see if they are activated on this browser
messaging.getToken({ vapidKey }).then((token?: string) => {
if (!token) return setNotificationsEnabled(false);
if (notificationsCfg[token]) setNotificationsEnabled(true);
});
}, [areNotificationsAllowed])

How to handle a subscribed user logging out?

In an application I am building, it is possible for a logged in user to receive specific push notifications related to activity their user account is participating in or subscribing to.
As it stands at the moment, if a user logs out, they remain subscribed and the service worker remains registered.
However, it would mean that push notifications they've subscribed to will still be received.
On the plus side, however, it means that if the original user logs in again, they won't need to go to their preferences and re-enable notifications and re-register a new service worker/subscription.
Does anyone have any examples of how to approach this in a secure way so notifications are not leaked after logging out, but maintaining the existing subscription in case they log back in? Is it even possible?
Thanks,
P
Usually you have an endpoint in your database associated to a user ID, so that you can target that user with push notifications.
When the user logs out you can simply remove the association between the endpoint and the user ID in your database.

Is it really necessary to update the subscription on every page load?

I'm currently working on a web app which will allow a user to subscribe to push notifications. We'll store the subscriptions in a database table mapped against the user's ID and when a notification needs to be sent, we'll look up the user's subscriptions and send the notifications.
I've been following this guide:
https://developers.google.com/web/fundamentals/codelabs/push-notifications/
All is going well, but something just doesn't feel "right".
On every page load, the service worker is registered, then it checks if they're already subscribed, then even if they are it calls updateSubscriptionOnServer() which contains the following comment:
// TODO: Send subscription to application server
This effectively means that every page load is going to be attempting to write the same subscription back to the database. Obviously we'll handle that in the application, but it doesn't seem ideal.
With the Web Push API, is this the expected approach?
Many thanks
Yes it can be useful to send the subscription to server on every page load:
The user may have changed permission from blocked to granted (or default) in the browser settings, so you want to create the subscription and send it to the server
The subscription endpoint may change for different reasons, so you need to make sure that the current endpoint is sent to the server (the previous endpoint will return 410 Gone)
A compromise between the points above and performance can be to send the subscription to the server only on given pages (e.g. homepage).

Get device token with react native

Is there any way to get the device token for notifications on demand with react native? It seems, from the docs, like the only time the token is exposed is on the PushNotification register event.
More generally, what's the common practice for handling device tokens?
If one user logs into my app, the app requests permissions from PushNotification, the register event is fired and I can associate that device with the logged in user. So far so good, but if that user logs out, and I break that association to stop the notifications, what do I do when another user logs in? The app already has permissions, so register won't fire again. How do I get the device token to associate it with the new user?
Or am I thinking about this the wrong way?
It seems my assumption that the register event only fires when the user grants access was the problem. The register event will fire in response to a call to requestPermissions whether or not the user was prompted. So by requesting permissions and responding to the register event when the app loads, you can always get the device id. Like so:
PushNotificationIOS.addEventListener('register', (token) => {
... store or use the token here ...
});
PushNotificationIOS.requestPermissions();

Best practices for push notifications in multi user applications?

I'm working on a push architecture that needs to support applications which allow for multiple users. This means more than one user can log into the application with their credentials. The problem I'm running into is what if user A allows push notifications, then logs out, then user B logs in and starts getting user A's push notifications?
What are some best practices for handling this type of thing? One thought I had was you could remember the last user who logged in and only display push notifications to the "logged in" user. You would have to send some sort of user context in the message payload so it could be checked against the logged in user. However this feels a little funky.
Anyone else ran into this? It's seems like a really relevant problem, especially for tablets where families tend to share the device.
We're implementing this by Registering the device with APSN, getting the device token and sending this to our server through a ws.
On the server side the device token is only associated with the last logged in user.
New app
User A (first ever user) uses IPAD A
Register with APSN, get token
Send token to our servers through ws
Search for token in db, token is new, store it
assign token to USER A
Next user logs into app
Register with APSN, get token
Send token to our servers through ws
Search for token in db, token exists already
Remove connection to USER A
assign token to USER B
SEND Notification to device WITH USERNAME
if username is logged in show it - else dont
Still not perfect as its sent to home screen first so to ALL users
I think your suggestion is acceptable in a multi-user app. It is much simpler to implement this in the client side, than on the server side. The downside is extra bandwidth wasted to send an unneeded notification. But vast majority of the usage is probably single-user so this may not matter much.
The alternative is to track the logged on users on your server and their current reg_ids. This could be more complicated because A could be logged on on multiple devices, then logs out from device 1, and B logs onto device 1, etc. and your server has to track all of these. So probably another table to track the relationships between 'Logged On Users' to 'Reg Ids'.
If you hate the idea of sending unneeded notifications, go with the server route. If you value Keep-It-Simple principle, go with the client route.
Let's suppose users of your app can logging on multi devices.
We have to make two API on server side:
func setUserDeviceNotifyToken(userId: Int, deviceToken: String) {}
func removeUserDeviceNotifyToken(userId: Int, deviceToken: String {}
On your app side, you have to call setUserDeviceNotifyToken API on every Login In and call removeUserDeviceNotifyToken on every logout.
On server side, you can track every user with its deviceNotificationToken and send notification for correct device.
Notice: If your service doesn't suppose to support multi device login with one user, you can handle it just by one updateUserDeviceNotifyToken and pass null for remove user's device token.
Notice 2: Do not let user logout before calling removeUserDeviceNotifyToken API.

Resources