Skip to content

Token caching breaks deleted token refresh  #7880

@bars0um

Description

@bars0um

Environment

  • Xcode version: 12.4 12D4E
  • Firebase SDK version: 7.9.0
  • Installation method: CocoaPods (select one)
  • Firebase Component: Messaging

Steps to reproduce:

Delete your token and try to fetch a new one:

messaging().deleteToken();

messaging().getToken();

The returned token is not a fresh one and checking the firebase api shows that the relating instance id is no longer there.

curl https://iid.googleapis.com/iid/info/fEVWIR1VoErnl-..ASm? -H "Authorization:key=YTsagf32...-c_azdc4"

{"error":"No information found about this instance id."}

The only way to fix this is to remove the caching logic from the Firebase/InstanceID pod.

To prove that there is something wrong here, I've commented the cached token logic in Firebase/InstanceID/FIRInstanceID.m and this seems to resolve the issue.

#Firebase/InstanceID/FIRInstanceID.m
....

//    NSString *cachedToken = [self cachedTokenIfAvailable];
//    if (cachedToken) {
//      if (handler) {
//        result.token = cachedToken;
//        handler(result, nil);
//      }
//      // If no handler, simply return since client has generated iid and token.
//      return;
//    }
..
//        FIRInstanceIDTokenInfo *cachedTokenInfo =
//            [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope];
//        if (cachedTokenInfo) {
//          FIRInstanceIDAPNSInfo *optionsAPNSInfo =
//              [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions];
//          // Check if APNS Info is changed
//          if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) ||
//              [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) {
//            // check if token is fresh
//            if ([cachedTokenInfo isFreshWithIID:identifier]) {
//              newHandler(cachedTokenInfo.token, nil);
//              return;
//            }
//          }
//        }
..

Relevant Code:

I've not had time to look at this closer, but something in the refresh token with iid logic is off. Appreciate if you could help shed light on this issue.

#Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m
...

- (BOOL)isFreshWithIID:(NSString *)IID {
  // Last fetch token cache time could be null if token is from legacy storage format. Then token is
  // considered not fresh and should be refreshed and overwrite with the latest storage format.
  if (!IID) {
    return NO;
  }
  if (!_cacheTime) {
    return NO;
  }

  // Check if it's consistent with IID
  if (![self.token hasPrefix:IID]) {
    return NO;
  }

  // Check if app has just been updated to a new version.
  NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion();
  if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) {
    FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004,
                             @"Invalidating cached token for %@ (%@) due to app version change.",
                             _authorizedEntity, _scope);
    return NO;
  }

  // Check if GMP App ID has changed
  NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID();
  if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) {
    FIRInstanceIDLoggerDebug(
        kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged,
        @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID,
        currentFirebaseAppID);
    return NO;
  }

  // Check whether locale has changed, if yes, token needs to be updated with server for locale
  // information.
  if (FIRInstanceIDHasLocaleChanged()) {
    FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged,
                             @"Invalidating cached token due to locale change");
    return NO;
  }

  // Locale is not changed, check whether token has been fetched within 7 days.
  NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970];
  NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds();
  NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp;
  return (timeSinceLastFetchToken < kDefaultFetchTokenInterval);
}

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions