How to handle a subscribed user logging out? - push-notification

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.

Related

Weird firebase email verification

I am creating a messenger app. In order to register a new user what I want is to get email and password from the user and before creating the account I want to verify the email provided by the user.
But the problem with firebase email verification is that you have to create account/user first then you can send the email verification link to the user.
Now this can lead to major problem: Suppose if some fake user used my email and created account but failed to verify email. But still he manages to create an account with my email.
So if later I will try to register my self to the app then I am firebase is going to show me Email already used.
To solve this issue I want to delete account created if user fails to verify his email just after he tried to register himself.
To do this I created an email verification screen which is pushed as soon as new user register through his email and password. Now here app will be waiting for user to verify his/her email by clicking the link send by firebase. I have also provided a cancel verification button. So if user cancel the verification I am just deleting the account which was already created. I am also handling if user press back key without verifying email which will also delete the user account.
Main Problem: Now the the last thing I need to handle is if user force quit the app. In order to handle this I tried to delete the account in dispose method as well as I used WidgetsBindingObserver. But both of them doesn't work for me.
Please help me to solve this!
The idea of email Link verification was created to solve this problem. Instead of creating an account and then verifying the email after, the account is just directly created from your email. So obviously you must have access to the email to create the account. See https://firebase.flutter.dev/docs/auth/usage/#email-link-authentication for details on how to implement this style of link authentication.
A similar discussion of how to handle quitting the app is occurring here How to execute code before app exit flutter . However abrupt quits from an app whether done by the user or the system are hard to handle by nature.
I wouldn't recommend deleting the account when quitting/ closing etc. the app since it is something legitimate users may do before confirming their email (especially if the email is delayed in being sent for whatever reason). This will cause a lot of frustration.
You could setup a Cloud Http Task to trigger the deletion of that account after a certain time (e.g. a few hours) of the account not being registered.
If they do register in time, you can cancel the task before it runs.

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])

STOP Push notification after logout

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.

How can I know that a Firebase Cloud Messaging token is out of use?

A single user can have multiple devices connected to his account.
Because of that he can have multiple cloud messaging tokens.
Everytime the user opens the app the token from that device is send to the app server and saved there.
What happens if a user uninstalls the app from one of his devices? I have no chance to tell the server that the token is not longer in use.
Can it occure that I notify an other user instead since this other user has acquired the not longer used token from the original user?
What happens if a user uninstalls the app from one of his devices?
Usually, when your app is uninstalled, it is advisable for you (the developer) to automatically make sure that the corresponding registration token is deleted from your own App Server.
Can it occure that I notify an other user instead since this other user has acquired the not longer used token from the original user?
No. Each registration token is unique per each app instance. So rest assured that if a registration token is invalidated/expires for whatever reason, no other user will be able to use it. Sending a message to an invalid/expired registration token will result to a NotRegistered error.
Tokens are not re-used so there should be no risk of notifying another user. Tokens cannot be acquired by one user from another.

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