Skip to content

[iOS][FCM] Cannot get new token when use 'messaging().deleteToken()' #3714

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 of 10 tasks
kratuwu opened this issue May 29, 2020 · 42 comments
Closed
2 of 10 tasks

[iOS][FCM] Cannot get new token when use 'messaging().deleteToken()' #3714

kratuwu opened this issue May 29, 2020 · 42 comments
Labels
plugin: messaging FCM only - ( messaging() ) - do not use for Notifications type: bug New bug report Type: Stale Issue has become stale - automatically added by Stale bot Workflow: Waiting for User Response Blocked waiting for user response.

Comments

@kratuwu
Copy link

kratuwu commented May 29, 2020

Issue

I need to delete token and get renew token, I try to use messaging().deleteToken()

await requestUserPermission();
const token1 = await messaging().getToken();
console.log(token1);

await messaging().deleteToken();

const token2 = await messaging().getToken();
console.log(token2);

For Android working find but iOS still log same value of token2 and token1

{
  "@react-native-firebase/app": "^7.1.0",
  "@react-native-firebase/messaging": "^7.1.0",
  "react-native": "^0.62.2",
}

Project Files

Javascript

Click To Expand

package.json:

{
  "@react-native-firebase/app": "^7.1.0",
  "@react-native-firebase/messaging": "^7.1.0",
  "react-native": "^0.62.2",
}

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def add_flipper_pods!(versions = {})
  versions['Flipper'] ||= '~> 0.33.1'
  versions['DoubleConversion'] ||= '1.1.7'
  versions['Flipper-Folly'] ||= '~> 2.1'
  versions['Flipper-Glog'] ||= '0.3.6'
  versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
  versions['Flipper-RSocket'] ||= '~> 1.0'

  pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'

  # List all transitive dependencies for FlipperKit pods
  # to avoid them being linked in Release builds
  pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
  pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
  pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
  pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
  pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
  pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
  pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end

# Post Install processing for Flipper
def flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == 'YogaKit'
      target.build_configurations.each do |config|
        config.build_settings['SWIFT_VERSION'] = '4.1'
      end
    end
  end
end

target 'AwesomeTSProject' do
  # Pods for AwesomeTSProject
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  target 'AwesomeTSProjectTests' do
    inherit! :complete
    # Pods for testing
  end

  use_native_modules!

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  add_flipper_pods!
  post_install do |installer|
    flipper_post_install(installer)
  end
end

target 'AwesomeTSProject-tvOS' do
  # Pods for AwesomeTSProject-tvOS

  target 'AwesomeTSProject-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end

AppDelegate.m:

#import <Firebase.h>
#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Add me --- \/
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  // Add me --- /\
  // ...
#if DEBUG
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"AwesomeTSProject"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end
#import <Firebase.h>
#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Add me --- \/
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  // Add me --- /\
  // ...
#if DEBUG
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"AwesomeTSProject"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end


Android

Click To Expand

Have you converted to AndroidX?

  • my application is an AndroidX application?
  • I am using android/gradle.settings jetifier=true for Android compatibility?
  • I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->


Environment

Click To Expand

react-native info output:

 System:
    OS: macOS 10.15.4
    CPU: (8) x64 Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
    Memory: 26.86 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.16.3 - /var/folders/vk/pccdnwks6fq_srvd380n8d9c0000gn/T/yarn--1590772235623-0.7141058862741598/node
    Yarn: 1.22.4 - /var/folders/vk/pccdnwks6fq_srvd380n8d9c0000gn/T/yarn--1590772235623-0.7141058862741598/yarn
    npm: 6.14.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.8.4 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 23, 27, 28, 29
      Build Tools: 27.0.3, 28.0.3, 29.0.2
      System Images: android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom, android-R | Google Play Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6241897
    Xcode: 11.5/11E608c - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_181 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.11.0 => 16.11.0 
    react-native: ^0.62.2 => 0.62.2 
  npmGlobalPackages:
    *react-native*: Not Found
  • Platform that you're experiencing the issue on:
    • iOS
    • Android
    • iOS but have not tested behavior on Android
    • Android but have not tested behavior on iOS
    • Both
  • react-native-firebase version you're using that has this issue:
    • e.g. 5.4.3
  • Firebase module(s) you're using that has the issue:
    • e.g. Instance ID
  • Are you using TypeScript?
    • Y/N & VERSION


@kratuwu kratuwu changed the title [iOS][FCM] Cannot get new token when execute function 'messaging().deleteToken()' on [iOS][FCM] Cannot get new token when use 'messaging().deleteToken()' May 29, 2020
@mikehardy
Copy link
Collaborator

Just a guess, have you tried waiting / retrying and seeing if it changes?
Hypothesis: it is "more than async", in that the await is returning but there is some network process still happening outside of the Promise return, and it will resolve to a different value after some unknown amount of time passes.

Hypothesis could be wrong but easy test to run

@kratuwu
Copy link
Author

kratuwu commented May 30, 2020

@mikehardy Yes, I have tried and reload the app again but still got the same value. It happen only iOS, for android it’s working find

@mikehardy
Copy link
Collaborator

I don't mean "reload", I mean in the very same execution context - not with an app reload that would call deleteToken again, after a single delete call, retrying the fetch token a few times (with exponential back-off maybe) to see if it changes underneath the code

@kratuwu
Copy link
Author

kratuwu commented May 31, 2020

@mikehardy Yes, I mean I have tried it both.

const token1 = await messaging().getToken();
console.log(token1);
await messaging().deleteToken();
const token2 = await messaging().getToken();
console.log(token2);
const token3 = await messaging().getToken();
console.log(token3);
const token4 = await messaging().getToken();
console.log(token4);
const token5 = await messaging().getToken();
console.log(token5);

still got the same token. When I try to reload app, it still got same token as before I reload and after that the token cannot use to register anymore.

I need to tell that everything working fine with Android but this issue happen only iOS. I'm not sure which method that is at issue deleteToken or getToken do not refresh new token

@mikehardy
Copy link
Collaborator

There is no sleep there, add a multi-second sleep, imagine network latency, replicated databases doing a 2-phase commit with consensus on multiple nodes in the apple cloud etc to persist the token - the hypothesis is it could take a couple seconds to come back. Wait as long as a minute maybe between the delete call and the final token log to really see if it is some cloud process

Sorry to pester I just don't think the awaits here are enough to be the test I was looking for yet

@kratuwu
Copy link
Author

kratuwu commented May 31, 2020

@mikehardy I have already tried to sleep 1 minute is it enough for you? and if it's related to response time, why everything working fine "react-native-firebase": "5.5.6"?

@mikehardy
Copy link
Collaborator

1 minute's good - thank you. Difference between 5.x and 6+ - no idea but I know there was a lot of work in the area and the crew was happy after they finished testing everything in #3339 - perhaps this was missed though, have you tried tracing through or instrumenting deleteToken to make sure it is called?

@kratuwu
Copy link
Author

kratuwu commented Jun 1, 2020

@mikehardy Yes, it is called fcm api when execute messaging().deleteToken()

@mikehardy
Copy link
Collaborator

@kratuwu that is both fortunate and unfortunate - unless there is some caching on the token in this module (does getToken() do any caching in the javascript or the objective-C in this module? I doubt it) then this indicates either an unsupported test scenario (possible but unlikely) or an upstream bug in https://github.com/firebase/firebase-ios-sdk - have you looked there?

I notice you specified package.json versions at ^7.10 which should include the most up to date iOS SDK (4db9dbc) so I'm not sure where else to look if not in the underlying SDK now

@mikehardy
Copy link
Collaborator

@kratuwu it appears that @dackers86 reproduces this in his (unrelated, but in the same area) work today, and points towards the underlying SDK if my understanding is correct: #3725 (comment) - have you looked upstream yet? they may have an open issue

@kratuwu
Copy link
Author

kratuwu commented Jun 2, 2020

@mikehardy I saw this pull request firebase/firebase-ios-sdk#5339 look similar but was merged since April.

@mikehardy
Copy link
Collaborator

That one looks to have shipped in SDK release 6.23.0, and you should be on 6.25.0, you can verify with Podfile.lock - might be a fresh issue 🤔 - I'm sorry I haven't been more help, you appear to have isolated the issue such that we're pretty sure you're calling APIs correctly, we're pretty we are calling the underlying APIs correctly, and I'm not much help beyond that 😞

@kratuwu
Copy link
Author

kratuwu commented Jun 2, 2020

Yes, my Podfile.lock SDK version is 6.25, Do you know this issue gonna fix soon?

@mikehardy
Copy link
Collaborator

I know nothing about this issue, unless @dackers86 was planning on taking it up with google in the firebase-ios-sdk repository directly I think the best course of action is to make a fresh issue there, perhaps linking back to this one, asking for help. They may require an Objective-C reproduction of it using only the underlying iOS APIs directly, but if this is an issue it should be very easy to reproduce

@dackers86
Copy link
Member

@mikehardy A bit of debugging on the IOS side suggests that the token that is returned after deletion is cached...

if (cachedToken) {
return cachedToken;
} else {
return nil;
}

@mikehardy
Copy link
Collaborator

@dackers86 sorry to pester - where did those lines come from? with github you can do get a permalink for a code line, then shift-select to get multiple lines like

https://github.com/firebase/firebase-ios-sdk/blob/7477e80f48be9563d513f022659c81067b844087/FirebaseMessaging/Sources/FIRMessaging.m#L609-L626

The problem is these seem to reference into Instance ID and I can't seem to find source for that one. If this is really an upstream bug we should file it though I think, seems serious!

@kratuwu do you get the new token if you restart the app but don't call deleteToken again? Said a different way, after a deleteToken, if it's a caching issue then an app restart should result in the new token showing up. Not ideal at all but would show it's a caching problem.

@kratuwu
Copy link
Author

kratuwu commented Jun 4, 2020

@mikehardy I got the new token when I delete the app and install again but not get the new one if just kill and reopen it.

@dackers86
Copy link
Member

dackers86 commented Jun 5, 2020

@mikehardy
Copy link
Collaborator

@kratuwu - as you are the interested parties here and it appears to be an upstream issue, the next step is for you (as a user of the upstream library too) is to open an issue upstream, with this info

@dackers86
Copy link
Member

Closing issue as the problem lies within the Firebase SDK, rather than RNF

@leurs247
Copy link

leurs247 commented Aug 4, 2020

I'm currently having the same problems with IOS. I'm using messaging().getToken() to get the token to store it in my database. After a logout, I use messaging.deleteToken() to delete the token.

Sign in: messaging().getToken(): abc123
[abc123 works here when testing through the firebase admin]
Sign out: messaging().deleteToken()
Sign in (2): messaging().getToken(): abc123 (I receive the same token)
[abc123 does not work anymore, so I think the token is invalidated on the firebase servers but the newest token is never returned).

When I reload the app after signing out, still nothing happens, I still get the same token. Only after a fresh install I get a new token.

Is there already a solution for this problem?

@mtieltjes
Copy link

As I was running into the same issue, and couldn't find any followup in this repo or the firebase-sdk, I took the liberty to file an issue at the firebase-sdk project.

Find it here: firebase/firebase-ios-sdk#6433

@mikehardy
Copy link
Collaborator

@mtieltjes nice! You might have more response there if you stick with their native example for a repro though - they have a habit of closing things based on repros above their stack vs in their stack https://github.com/firebase/quickstart-ios/tree/master/messaging

@golya
Copy link

golya commented Sep 16, 2020

@mtieltjes @yesterday24
here I wrote what is the issue in case of deleteToken firebase/firebase-ios-sdk#6433 (comment)

It is not clear where is the problem, on RNF or firebase-ios-sdk side.

@golya
Copy link

golya commented Sep 17, 2020

@dackers86 @mtieltjes @yesterday24
I started to debug more about what happens between the firebase-ios-sdk (FIS) with https://github.com/firebase/firebase-ios-sdk/tree/Messaging-4.6.2 FIRMessaging version 4.6.2 and react-native-firebase (RNF) version 7.8.4.

First of all it seems the FIS is storing the token info in a cache with key "senderid.*":
https://github.com/firebase/firebase-ios-sdk/blob/Messaging-4.6.2/Firebase/InstanceID/FIRInstanceIDTokenManager.m#L345

This is the only place where a hardcoded * is used everywhere else this constant is used:
https://github.com/firebase/firebase-ios-sdk/blob/Messaging-4.6.2/Firebase/InstanceID/FIRInstanceIDConstants.m#L33

The RNF from javascript always handle the token related things with scope 'FCM':
https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/lib/index.js#L142

It seems it is an accident that the getToken works on RFN side by the 'FCM' scope as it is get back by a handler that do not use the scope information when it tries to get back from the cache, that handler is use the constant kFIRInstanceIDDefaultTokenScope which is a "*":
https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/ios/RNFBMessaging/RNFBMessagingModule.m#L108
https://github.com/firebase/firebase-ios-sdk/blob/Messaging-4.6.2/Firebase/InstanceID/FIRInstanceID.m#L214
https://github.com/firebase/firebase-ios-sdk/blob/Messaging-4.6.2/Firebase/InstanceID/FIRInstanceID.m#L239

And the problem starts when the deleteToken is invoked with scope 'FCM' and on the FIS side it try to use the 'FCM' scope which never existed:
https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/lib/index.js#L159
https://github.com/firebase/firebase-ios-sdk/blob/release-6.30.0/Firebase/InstanceID/FIRInstanceIDTokenManager.m#L149

On our side with these version this is what exactly happens. So my question from the developers of RFN is why did you choose the 'FCM' as the default scope if the default is '*' in the FIS?

Can it happen that the fix should be that add '*' as scope at deleteToken here:
https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/lib/index.js#L159

@mikehardy
Copy link
Collaborator

@golya that is champion troubleshooting! Seriously, great digging.

I've asked @Salakar internally and attempted to look through firebase-js-sdk (which we pattern off of frequently, for API: https://github.com/firebase/firebase-js-sdk/) but not come up with anything.

A parallel implementation that is sometimes useful for comparison is FlutterFire https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/lib/firebase_messaging.dart but don't have the time to dive in fully

I'm going to re-open this while it's under consideration

@mikehardy mikehardy reopened this Sep 17, 2020
@golya
Copy link

golya commented Sep 18, 2020

@mikehardy thanks for the help!

It seems the FlutterFire use handler everywhere (which probably means it using the default scope):
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m#L156
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m#L166

In this case I think the RNF should use the deleteIDWithHandler as well in case of deleteToken.

On the other hand I have conversation with @chliangGoogle who is a contributor of firebase-ios-sdk, and I try to figure out how can you use an own scope with the cache, because based on the firebase-ios-sdk code it seems impossible, and probably I am wrong.

@mikehardy
Copy link
Collaborator

Very interesting @golya - I'm listening here and I think either direction (just using handler, or fully handling scopes) seem like fine ways to go for the RNFB use case. It does seem based on your investigation that there is a problem to fix and just staying the way it is now is not correct. Please come back with whatever findings you obtain from the firebase-ios-sdk collaboration

@tuan-hma
Copy link

tuan-hma commented Sep 28, 2020

Since the problem is currently under consideration (i guess), as a temporary fix for anyone stuck in emergency, as suggested by @golya using deleteIDWithHandler seem to solve the problem for me.
You can directly change source code at : /node_modules/@react-native-firebase/messaging/ios/RNFBMessaging/RNFBMessagingModule.m looking for deleteTokenWithAuthorizedEntity method. I tried to add the following code after deleteTokenWithAuthorizedEntity and it seems to work.

[[FIRInstanceID instanceID] deleteIDWithHandler:^void(NSError *_Nullable error) {
    }];

Also, another workaround is using messaging().deleteToken(undefined, '*') instead.

@mikehardy
Copy link
Collaborator

@tuan-hma excellent - note that you can (and I recommend it...) use https://github.com/ds300/patch-package to make those changes reliably + safely if you haven't seen it

I haven't heard anything definitive further on this (@Salakar was sick when I asked before - maybe he has time now 🙏 ) so I'm not sure if he has an opinion on how to handle this

@mikehardy mikehardy added Workflow: Needs Review Pending feedback or review from a maintainer. type: bug New bug report plugin: messaging FCM only - ( messaging() ) - do not use for Notifications labels Sep 28, 2020
@mikehardy
Copy link
Collaborator

mikehardy commented Sep 30, 2020

@golya I re-read everything and your approach to use default scope (from here #3714 (comment)) seems fine to me in the absence of any dissent (and there has been no dissent). If you want to propose a PR to do that, I will merge it and we can move on. My only question in the PR would be to consider whether existing tokens become invalid after the change such that it means apps need to fetch new tokens on the update. I don't think they do, so my point is mostly just to consider the change impact on existing user base to make sure

edit: related conversation for posterity: firebase/firebase-ios-sdk#6433

@golya
Copy link

golya commented Oct 6, 2020

@mikehardy ok, if I have time I will do a pull request and yes it is possible to do the whole thing with scope (which means that is possible to do it without breaking change.)

@Stevemoretz
Copy link

@golya

Any news on this?

@golya
Copy link

golya commented Nov 3, 2020

@Stevemoretz not yet, I can not estimate right now when will have time to finish the pull request.

@Stevemoretz
Copy link

@golya

I found a workaround, passing (undefined,'*') in the function makes it work on both Android and ios.
Then request a new token and you'll get one.

@joshallison
Copy link

joshallison commented Dec 9, 2020

Inside my app I received a valid token the first time I installed / launched the app, but on subsequent launches received invalid tokens from getToken().

I had to call await messaging().deleteToken(undefined,'*') followed by await messaging().getToken(undefined,'*') to get valid tokens.

@mikehardy
Copy link
Collaborator

@joshallison tokens should be stable, if you get new tokens on launch you likely have some other module invalidating/requesting tokens, and in my experience based on other issues in this repo it will be maddening

@SnaiNeR
Copy link

SnaiNeR commented Dec 10, 2020

@golya @tuan-hma
I am very grateful to you, thanks for the crutch, I hope the profit from the notifee did not blow the head off the library maintainers at all ....

@stale
Copy link

stale bot commented Jan 10, 2021

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Jan 10, 2021
@mikehardy
Copy link
Collaborator

Just a note since this is the group of most interested parties: next version of native SDKs removed support for custom token scopes, however I tested the deleteToken/getToken path (via a check in our automated test suite here) and the new version of the SDKs seem to behave correctly. Pay attention when v12.0.0 comes out here and let us know please if this issue crops up again after removing the token scopes we're using for v11.x. Thanks!

@MoOx
Copy link

MoOx commented Jun 2, 2021

Confirming that deleteToken() now works properly! Thanks for everyone involved in this update.

@BlagojeV93
Copy link

I was experiencing the same issue from the top of the thread, where I was unable to retreive fresh token once I execute deleteToken() method on my app's logout. However, I was able to achieve it if I combine messaging().unregisterDeviceForRemoteMessages() with messaging().deleteToken() on my logout action.

Is this currently the correct way to achieve this behavior, or am I missing something?

I have latest versions of react native at 0.73.1 and @react-native-firebase/messaging at 18.7.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: messaging FCM only - ( messaging() ) - do not use for Notifications type: bug New bug report Type: Stale Issue has become stale - automatically added by Stale bot Workflow: Waiting for User Response Blocked waiting for user response.
Projects
None yet
Development

No branches or pull requests