firebase-android-sdk icon indicating copy to clipboard operation
firebase-android-sdk copied to clipboard

Messages Still Received on Deleted Firebase Messaging Token

Open TarekkMA opened this issue 10 months ago • 14 comments

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:

  1. Subscribe to a topic named test_topic.
  2. Send a message to test_topic and confirm it's received.
  3. Invalidate the current Firebase Messaging token:
    • Invoke deleteToken()
    • Then, request a new token with getToken()
  4. Verify that the new token is different from the previous one.
  5. 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.
  6. 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.

TarekkMA avatar Apr 03 '24 08:04 TarekkMA

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!

argzdev avatar Apr 05 '24 10:04 argzdev

Hi @argzdev, thank you for the information.

TarekkMA avatar Apr 05 '24 11:04 TarekkMA

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?

sumittiware avatar Apr 05 '24 11:04 sumittiware

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.

princebansal avatar Apr 05 '24 14:04 princebansal

@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 avatar Apr 05 '24 14:04 argzdev

@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.

princebansal avatar Apr 05 '24 14:04 princebansal

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 avatar Apr 05 '24 14:04 argzdev

@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.

princebansal avatar Apr 05 '24 15:04 princebansal

@argzdev Any updates on this?

princebansal avatar Apr 08 '24 09:04 princebansal

Hi @argzdev Waiting for revert on this

princebansal avatar Apr 10 '24 14:04 princebansal

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.

argzdev avatar Apr 11 '24 13:04 argzdev

Sure @argzdev . Thanks for the update

princebansal avatar Apr 11 '24 18:04 princebansal

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!

google-oss-bot avatar Apr 18 '24 01:04 google-oss-bot

Waiting for updates from @argzdev

TarekkMA avatar Apr 18 '24 08:04 TarekkMA

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 avatar May 21 '24 09:05 lehcar09

@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.

princebansal avatar May 21 '24 13:05 princebansal

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!

Zachary625 avatar Jun 19 '24 02:06 Zachary625