We're using onDisconnect() function to remove inactive user sessions and we noticed that sometimes the session is still there, even though the user disconnected. After some debugging we came to a conclusion that it's caused by expired tokens - onDisconnect() can't remove a node if it's not authenticated.
If I understand correctly the token is normally automatically refreshed every ~55 minutes (it's valid for one hour, so there is a 5 minute buffer). However, it seems that Page Visibility API is used to disable this behavior when the tab is inactive. So after the tab or the browser window is inactive for more than an hour and you switch back to it, the token is expired, Firebase client reconnects and gets new token - in which case it's possible to somehow recover from failed onDisconnect(). But when you never go back to the tab and just close the browser there's no way to properly remove the data.
I can think of two workarounds for this. One would be to manually refresh the token, even if the tab is inactive. The other would be to go offline when the tab is inactive, before the token expires. However I think that it should be done in the SDK itself, not in the user code, or at very least this behavior should be somehow documented.
Check out this fiddle:
https://jsfiddle.net/625dLa9j/
When you add some value, close the tab, and then reopen it, the value should be removed. But when you leave the tab in background for more than 1h, the value will still be there.
We can't refresh tokens when the tab is inactive. That would be quite inefficient, expensive and detrimental to some users. If you need to run stuff in an inactive tab, you will need to do it manually.
I don't think that's a very satisfactory reply to @marszall87's issue. Having a reliable presence system seems very core to the Firebase experience.
The Auth team has no plans to proactive refresh tokens when a tab is not visible. My answer is pretty clear. I have currently 50 tabs open on my workstation. Do you really think it is a good idea to proactively refresh tokens on every tab? Anyway, we provide APIs for developers to refresh on their own. We can't make this the default behavior.
Uh, okay, one, that was rude, two, what's the user story for people who have auth'd user sessions but still want reliable data removal via onDisconnect? Sure, you can reject OP's suggestion for a fix, but I'd at least expect some guidance given.
You can get the expiration of the token at any time. It is in the exp field in the token. Based on that you can implement your own token refresh logic. To force a token refresh, call firebase.auth().currentUser.getToken(true). You can run your logic even when the app is not visible.
This probably bears mention in the onDisconnect docs:
https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect
On Wed, Oct 4, 2017 at 2:38 PM, bojeil-google notifications@github.com
wrote:
You can get the expiration of the token at any time. It is in the exp
field in the token. Based on that you can implement your own token refresh
logic. To force a token refresh, call firebase.auth().currentUser.
getToken(true). You can run your logic even when the app is not visible.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/firebase/firebase-js-sdk/issues/174#issuecomment-334297233,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAlbyJyofpsTzwcz2mVDnfs0flObrYOsks5so_rLgaJpZM4PnLPd
.
Hey @marszall87 and @vincentwoo, to further clarify, we try to minimize activity in the background/when the app is not visible for multiple reasons:
The Auth team can't apply this as a default as the downsides are far worse than the upsides.
Tom from RT database team, I don't think this is an auth problem but maybe it is a database problem. We check the token twice when 1. the onDisconnect is enqueued and 2. when the onDsiconnect is applied. Maybe 2 is not necessary given the connection has been authenticated already and the expected use of the feature. It does mean revoking the auth key won't prevent pending onDisconnects to be stopped, but it would stop new onDisconnects from being enqueued. So I personally think that is enough security wise but I would need to raise this with security as it would be a novel policy for handling expiring tokens.
Re-opening as this could be solved from the Database side.
Thanks for you reply @bojeil-google . I understand that it's important to minimize the activity in background tabs, so what about my second suggestion, i.e. going offline (disconnecting from database) just before the token expires? It should solve the problem as onDisconnect will fire with valid token.
Thanks for the feedback. This is an interesting suggestion, though not something we could change directly since it may break existing apps. If we were to do this, it would have to be behind an option or something. So for now, I think you probably need to implement this yourself (call firebase.database().goOffline() when the tab goes to the background). But we'll keep this feedback in mind.
Any updates on this for a flutter app , how should we handle this?
I totally get the obvious need to minimize activity in the background. But the explanation "it is common to open dozens of tabs and keep them open indefinitely" exactly what makes this issue relevant? If we know most people will keep their tabs opened longer than an hour, we can't rely on onDisconnet() method at all.
I rely on onDisconnect in my app to manage user's connections and session data and it seems like I am affected by this issue as well. Are there any updates on this issue?
How a developer can build a presence module with this issue? onDisconnect doesn't work!!!