How to reliably stop receiving notifications when user logs out - firebase

I have a server, and multiple clients (web & mobile). When my users log in, I want to start sending them notifications about the content they follow. When they log out, I want to stop sending them notifications.
I've found many Stack Overflow questions that are similar to mine, but none have been completely answered.
The closes to my question was this other question where the accepted answer is to call deleteInstanceId() when the user logs out, which seems like the most solid solution, but in the comments someone copy pasted from the (GCM) docs that "Developers should never unregister the client app as a mechanism for logout or for switching between users". I wasn't able to find the same notice in the new Firebase docs, but I assume that it's the same concept: the InstanceId is not supposed to be user related.
The only alternative I've found, is to send a "signOut" request to my server, with the instanceId, and my server needs to remove the associated instanceId from the user account.
But what if that API call doesn't go through? This seems to be quite a fragile solution.
So this is what I would do now:
Send the instanceId to my server when the user authenticates
Make sure that this same instanceId is not used by another user, since this could happen when the other user logged out on the same device, but the API call didn't go through
When sending notifications, send them directly to the registered instanceIds (initially I had planned on using topics, but in combination with handling my tokens, this seems even more fragile).
When the user logs out, send a signOut request to my API, and remove the instanceId from the user.

Your question seems to just be seeking validation for a design, which really isn't the purpose of Stack Overflow. The Firebase subreddit might be a better alternative for drumming up conversation around the problem.
But I will say that if it works for you, then run with it. Consider also sending the target users's UID in each message, and have your app compare that with the currently signed in user in order to determine if it reached its correct destination. Send a message back to the server if it's not in order to correct the problem.

Related

Firebase AppCheck VS hackers & spammy requests

Although I fully understand the use of AppCheck, I still wonder how it can help against spamming request to an API endpoint.
In the scenario of a hacker using OpenBullet or whatever hacker tool to spam thousands of requests per minutes to a specific endpoint (for example, a Signup endpoints to create thousands of fake profiles in a social app):
once the hacker got their hand on the appcheck token from the device, can't they simply attach it to the request's header, and spam all they want the api endpoint that we secured from our backend by checking appcheck token?
I mean, as long as the TTL didn't expire, I guess all their requests will pass the check thus they could use their hacker tool and pretend to come from the untempered app? Or am I missing something?
I guess a solution would be to:
1- forceRefresh the appcheck token on each fetch request from the mobile app
2- expire the received appcheck token programmatically after successful verification from the backend, so that further request would need a new one that can only be generated from the app, thus making it harder for the hacker?
Any help is appreciated! :)
I'll put it in a different way. While AppCheck offers a level of protection to your resources, it does not guarantee 100% protection. The sample you gave is an instance on how it could be bypassed. But what can't be factored out is that AppCheck makes it harder for a malicious actor to roam around your services and consume them on your budget.
Take a look at this section from the documentation. Also take a look at this question as it was asked after your question and had a firebaser (Frank) corresponding to it.

Implementing a notification system for sending/accepting friend request using firebase cloud functions and firestore

I am trying to implement a notification system for handling notifications similar to friend request notifications. For example, I write the email of the person I want to send a friend request to. then click on send request. I am confused as to after that, what exactly should happen?
Right now I am thinking that on clicking send request, I would create a document in cloud firestore in a 'notifications' collection, which would then invoke a cloud function that sends a push notification to the user with that email. The user now has the option to accept or deny the request. Choosing any of those actions would update the notification document which will again invoke a cloud function that would add both users to each other's friends list and notify the first user.
So my questions are: -
Is this method reasonably good to be implemented in a production app since it is involving many cloud function invocations and document read and writes? Or even better question - How would you implement something like this in a production-grade app?
Is there any other method that is secure (in the sense that no one should be able to wreck this process by changing the code on the frontend) and efficient (less read/writes/invocations)?
Can this be done without creating any document whatsoever? Purely by cloud functions? Then would it be able to capture other user's response to friend request and do the necessary changes?
For the problem you are describing I would approach it in the say way you are doing, and in fact there are not that many operations going on here, since you would have 2 Firestore writes and 2 invocations of cloud functions, not to mention that the second invocation could take a long time to be fired depending on the user's actions, so you don't need to be more efficient than that.
To you final question I would say that it would be difficult to have this implemented without information going through Firestore because you need to store the acceptance of the friend request, and for the same reason mentioned above, you need to store that information somewhere, even if temporarily.
I know I'm late but maybe this will help to someone else.
My way adding sent - receive friend request system is following:
For example:
me:
{
name:'John',
id:'20'
};
stranger:
{
name:'Lucas',
id:'50'
}
When I click add friend (on stranger) I will call function:
addDoc(doc('users', stranger.id, 'receivedFriendRequests'), { user:me });
This function will add ME into his receivedFriendRequests docs so he will be able to get that docs and check users who sent request to him.
So, in notifications Component you have to just get your receivedFriendRequests` docs and map all users and make function to accept friend requests for each of them.
When you click accept you need to delete that user from receivedFriendRequests and store both users in "friends" collection. You can do it in your own way, but I give the best example, in my opinion.

Firebase - Automatically sign out user onDisconnect

Since I have noticed that once a user signs in with email and password, on reopening the application the session will not have expired and there is no need for a new authentication, I wish to avoid this.
I want to automatically .signOut() a user when .onDisconnect is triggered. How can I achieve this? I have tried with the following code, but unsuccessfully:
firebase.auth().onDisconnect().signOut();
When you say "onDisconnect", I'm assuming that you mean Realtime Database onDisconnect triggers.
The first thing to know about onDisconnect is that it triggers when the socket connection between Realtime Database and the client app is closed. This could happen for any number of reasons, and it can happen at any time, even if the app seemingly has a good internet connection. So, be careful about what you're trying to do here.
Also, onDisconnect triggers can only affect data in the database directly, and nothing else. So, this limits what you can effectively accomplish. You can't perform any action in the client app in response on an onDisconnect.
Between these two facts, what you're trying to do isn't really possible, and, I don't think it's desirable. You could end up logging out the user just because their train went underground momentarily, or if they simply switched out of the application for some time. This would be massively inconvenient to the user.
If you want to automatically log out the user, I strongly suggesting finding some other way to do this, such as writing some code to remember how long it's been since the user used your app, and forcing the logout on the on the client app based on your preferred logic.
The onDisconnect() is related to the database connection, and has little to do with your authenticated user. As in: onDisconnect() may fire when your user is signed in, simply because the connection to the database drops temporarily.
But more importantly: onDisconnect handlers run server-side, once the server detects that the client has disappeared. When this is because if a dirty disconnect (e.g. the app crashes), there is no way for the client to detect this anymore.
The most likely approach you'll want is to simply sign the user out when they close the app.
Alternative you might want to attach a listener to .info/connected in your client. This is a client-side listener that fires when the client detects that it is connected or disconnected.

Receive callback (Backend) on validate fail

I'm serching for a solution for a backend and firebase same interesting, but I have some questions before starting to using it.
My question is related to this post (you don't need to read it) Firebase rate limiting in security rules?
The question was how to be sur the client can do the same request more than 1 time every 5 seconds. The anwser is fine. My question is:
If we assume the client app has no bug and it check if there is no more than 1 request every 5 seconds, the only way we can fail the "validate" is if someone is trying to hack (sending request without using the client app). Is there a way to send a callback to a admin user or to write something in the database to tell someone is trying to write faster than expected and the user is maybe a hacker?
Thanks
Security rule failures are not accessible through an API at the moment.
Look firebase is working on a new feature that will allow me to do that
https://firebase.google.com/docs/functions/
"With Cloud Functions database event handling, you can modify the Realtime Database in response to user behavior, keeping the system up to date and clean."

SignalR just for checking if user is online or not

I would like to ask, if it is a good idea to use SinglR just for knowing if the current user now online or not?
For example I have an small website with log in system, and some where on the side i would like to show the logged in members.
Is this a good idea to use signalr for that?
And if it the case should I then on each page start the connection with hub? (In this case when user navigates on the pages, will be the ReConnected method called on hub, or OnDisconnected and OnConnected)?
I'm just starting with signalr, so curious what ppl think.
You could use SignalR though there might be better methods to do this. So when a user logs in, logs out or becomes inactive - you would have some sort of message being sent from the client to the server that indicates the change in status. You can store that information in a temporary database and whenever a value in the database changes you can use SignalR to relay that information to all the connected clients.
Signalr will get reconnected when the user moves from one page to another page. Whenever a user logs into a website the user security details will be persisted in a cookie assuming you are using Cookiebase authentication. So till the user logs out or session timesout the cookie will be active. So there is no real need for Signalr here.
I have been investigating the same thing. From my research, I would say that you COULD do this, but I'm on the fence of whether it's the best way to go about it. I would expect a LOT of disconnecting, connecting and reconnecting. If you're persisting this data in a database, you should anticipate a lot of database traffic. if you're only on a single server though, you could just persist this in memory.
Something to also note is that the ConnectionId changes with each page refresh. At first, I thought that was dumb because I wanted the connection id to be consistent so i could keep a handle on a user with it. However, if you open a link in a new tab and then close one of them, you have to still keep the other connection in storage. If the id was the same you would remove it on disconnect even though the other tab was open, so your user would incorrectly be marked as offline.
However, the other issue that i'm thinking about is that if you're just browsing around the site in a single tab, you will disconnect for a split second between each page load. So you might run into connection consistency issues with that.
I'd say online presence with signalr is more common to be used for a chat room or game lobby. So I'd say this is possible, but whether it's a good solution -- i'm unsure.

Resources