firebase-android-sdk
firebase-android-sdk copied to clipboard
Messages Still Received on Deleted Firebase Messaging Token
Environment Details
- Android Studio Version: Android Studio Iguana | 2023.2.1 Patch 1
- Firebase Component: Messaging
- Component Version: 32.7.4
Problem Description
Original Issue reported here: https://github.com/firebase/flutterfire/issues/12567
Issue Summary:
Messages are still received on a topic even after the Firebase Messaging token, which had subscribed to the topic, is invalidated and a new token is generated.
Steps to Reproduce:
- Subscribe to a topic named
test_topic
. - Send a message to
test_topic
and confirm it's received. - Invalidate the current Firebase Messaging token:
- Invoke
deleteToken()
- Then, request a new token with
getToken()
- Invoke
- Verify that the new token is different from the previous one.
- Attempt to send another message to
test_topic
. Notice that the message is still received, despite the fact that the token which had subscribed to it has been deleted. - Wait approximately 15 minutes and repeat sending a message to
test_topic
. The issue persists, indicating that messages are still delivered to a token that should no longer be subscribed to the topic.
Hi @TarekkMA, thanks for reaching out. This is working as intended. The invalidated tokens aren't immediately deleted. Our internal jobs run on a daily basis and thus the deletion and invalidation of FCM tokens should be done in a day or so.
Update: The best course of action would be to just subscribe and unsubscribe to topics as needed. Take note that both subscribe and unsubscribe calls are done in the background, ~~and there are no hooks that allows the SDK to detect when the subscribe/unsubscribe call completes, so there's also no guarantee how long the call may take,~~ but I think it'll be a lot shorter compared to the 1 day duration.
Let me know if this answers your question. Thanks!
Hi @argzdev, thank you for the information.
Hi @argzdev so, if we get the new token using getToken()
after calling deleteToken()
, the new token will be automatically subscribed to the older topics?
Hi @TarekkMA @argzdev. The original issue mentioned here https://github.com/firebase/flutterfire/issues/12567 is different from the one that is being discussed here.
According to the original issue, the new token generated after deleting the old token is preemptively subscribed to the topics the old token was subscribed to.
Here's an example of the observed behaviour with timeline:
--- T(x) is time, N(x) is token, TP(x) is topic
T0:
Token generated -> N1
T1
N1
is manually subscribed to TP1
and TP2
T2
N1
deleted
T3
Token generated -> N2
T4
N2
is automatically subscribed to TP1
and TP2
The last step at T4 is the real problem.
** How this affects our business use case? When the user logs out of the app, we delete the logged in user's token and allow user to log in anonymously and immediately generate a new token for the anonymous user. But since the new token is already subscribed to the topics that the logged user was subscribed to, it sends all the logged in user's notifications to the anonymous user. This results in a huge security issue, because we send sensitive information in the notifications too.
@sumittiware I've tested this now and this behavior is what's happening. However, I'm not sure if this is an intended behavior. I agree though, I believe resubscribing to the topic should be done, instead of it automatically subscribing to the older topic as mentioned in best practice from our documentations. I'll ask our engineer regarding this behavior.
Thanks for explaining this further, @princebansal. Although, I'm wondering is there any reason why we don't use unsubscribe to the topics? I think in your use case, you should be able to resolve this issue by unsubscribing the user whenever they log out.
Let me know if this helps. Thanks!
@argzdev Thanks for the quick response. Unsubscribing wont be possible because we have no stored information of the topics that the new token is subscribed to. We store token to subscribed topic data in our database and use that data to subscribe or unsubscribe a topic from a token. But since this new token is freshly generated, ideally our system has no stored topics against it. Hence we wont know which topics we should unsubscribe from.
In ideal scenario, the freshly generated token should come with no topics subscribed, and we should be given the control to manage topics for that token.
Sorry, I didn't clarify it further. You're correct calling unsubscribeFromTopic
to the newly generated token would not really do anything. But what I mean is to call this for the old token before you generate a new token, would it not be possible to call the unsubscribeFromTopic
?
In ideal scenario, the freshly generated token should come with no topics subscribed, and we should be given the control to manage topics for that token.
But yeah, I'm also under the impression that that's what's expected from the newly generated token. In the meantime, I've notified our engineers of this issue with internally tracking bug b/333061151. I'll keep you folks posted once I receive an update.
@argzdev That sounds a great workaround actually but there's a small catch. Our logout flow is a pure client side operation, where we just clear the auth token stored in the app and allow the user to log in anonymously by hitting the server. And I think that's how most of the systems that use JWT for authentication do.
We would need an app release where we have to introduce server intervention in logout. I would prefer to let the fcm do its job correctly.
Thanks again for the escalation, eagerly waiting for the updates on this.
@argzdev Any updates on this?
Hi @argzdev Waiting for revert on this
Hey @princebansal, it seems like our engineers are still taking a look into it. It'll take sometime before we can provide an update with this. Unfortunately, I'm unable to provide a timeline on when this will be moved forward. If you require an urgent solution, you could try what we've talked about earlier (using unsubscribeFromTopic
) as a temporary mitigation while our engineers are still conducting the investigation. I'll try to bump up the internal bug as much as I can to push it with priority.
Sure @argzdev . Thanks for the update
Hey @TarekkMA. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.
If you have more information that will help us get to the bottom of this, just add a comment!
Waiting for updates from @argzdev
Hi @TarekkMA, thank you for your patience. We have received a response from our engineer and according to investigation this is working as intended. For context, each FCM registration token contains the FID to target devices for message delivery. When you delete the token (deleteToken
), the FID is still the same.
i.e.
//Current token: dlrmE***:APA91bEH***
Firebase.messaging.deleteToken()
Firebase.messaging.token
//New Token: dlrmE***:APA91bFy***
This leads to the same subscription being associated. That said, we recommend deleting the FID when you delete the token. Thus, the Topics fanout to the old/deleted FID will not be delivered.
i.e.
//Current token: dlrmE***:APA91bEH***
Firebase.messaging.deleteToken()
FirebaseInstallations.getInstance().delete()
Firebase.messaging.token
//New Token: e4Mrm***:APA91bGy***
I'll go ahead and close this issue now. Let me know if there's any misunderstanding and/ or we need to reopen this issue for further investigation.
@lehcar09 Thanks for probing into the issue and providing a detailed explanation of the behaviour.
The recommended steps should definitely go in the relevant docs because I believe that the deleteToken() method doesn't convey the fact that the FID will stay same.
Hi @TarekkMA, thank you for your patience. We have received a response from our engineer and according to investigation this is working as intended. For context, each FCM registration token contains the FID to target devices for message delivery. When you delete the token (
deleteToken
), the FID is still the same.i.e. //Current token: dlrmE***:APA91bEH*** Firebase.messaging.deleteToken() Firebase.messaging.token //New Token: dlrmE***:APA91bFy***
This leads to the same subscription being associated. That said, we recommend deleting the FID when you delete the token. Thus, the Topics fanout to the old/deleted FID will not be delivered.
i.e. //Current token: dlrmE***:APA91bEH*** Firebase.messaging.deleteToken() FirebaseInstallations.getInstance().delete() Firebase.messaging.token //New Token: e4Mrm***:APA91bGy***
I'll go ahead and close this issue now. Let me know if there's any misunderstanding and/ or we need to reopen this issue for further investigation.
This also helped us as well, it would be nice to put this in official doc: https://firebase.google.com/docs/cloud-messaging/manage-tokens, this and the delay of actual token deletion are both quite important for production, thank you very much!