Skip to content
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

FBSDKAuthenticationToken.current returns the actual valid authentication token only after a certain delay #2417

Open
5 tasks done
GalBerezansky opened this issue May 8, 2024 · 7 comments

Comments

@GalBerezansky
Copy link

GalBerezansky commented May 8, 2024

Checklist before submitting a bug report

Xcode version

15.2

Facebook iOS SDK version

17.0.1

Dependency Manager

Prebuilt Binaries

SDK Framework

Login

Goals

I want to use FBSDKAuthenticationToken.currentAuthenticationToken when the user opens the application, this user has logged-in with the limited log-in in a previous session and I'd like to use his authentication token.

Expected results

To get a non-nil FBSDKAuthenticationToken.currentAuthenticationToken whenever it is called, it happens after the set-up of the facebook-ios-sdk, the facebook-ios-sdk should be useable at that time.

Actual results

In reality FBSDKAuthenticationToken.currentAuthenticationToken is nil when I first access it, I get the non-nil valid value only with a retry mechanism. With solid internet connection I get the non-nil auth token only after 0.4 seconds after the first call to the the method approximately.

The main issue is I don't know when the user is actually logged-out and when the authentication token in nil because of this delay, if the user logs-out via facebook's side I'll just run my retry mechanism until I reach time out.

It is worth noting that the exact same issue occurs with FBSDKAccessToken.currentAccessToken in the non-limited regular log-in. When I used version 12.3.1 of the sdk I got the valid non-nil value as soon as I accessed it, now I get the same delay there.

The currentAuthenticationToken isn't well documented, it isn't clear when it should be nil or not, it feels like there was a behavior change under the hood.

Bottom line, please explain when and why the authentication token is nil, when should I decide that the user is actually logged-out and when I need to wait/retry, an even better solution is to ensure that the FBSDKAuthenticationToken.currentAuthenticationToken and FBSDKAccessToken.currentAccessToken are accessible as soon as possible whenever they have a value, otherwise doc them to explain how they should be used.

Thanks!

Steps to reproduce

  1. Successfully log-in with the limited facebook log-in.
  2. Close the application.
  3. Re-open it, the first access to FBSDKAuthenticationToken.currentAuthenticationToken is nil even though the user should be logged-in.

Code samples & details

// The code the does the facebook log-in
- (void)loginWithPresentingViewController:(UIViewController *)presentingViewController
                                    block:(void(^)(NSString * _Nullable token, BOOL cancelled,
                                                   NSError * _Nullable error))block {
  auto configuration =
      [[FBSDKLoginConfiguration alloc] initWithPermissions:@[@"public_profile", @"email"]
                                                  tracking:FBSDKLoginTrackingLimited];
  dispatch_async(dispatch_get_main_queue(), ^{
    [self.loginManager logInFromViewController:presentingViewController
                                 configuration:configuration
                                    completion:^(FBSDKLoginManagerLoginResult * _Nullable result,
                                                 NSError * _Nullable error) {
      if (!result || result.isCancelled) {
        block(nil, result.isCancelled ?: NO, error);
        return;
      }

      if (![self.loginPermissions isSubsetOfSet:nn(result.grantedPermissions)]) {
        block(nil, NO, [NSError lt_errorWithCode:FORErrorCodeLoginFailed description:@"An error occured");
        return;
      }

      block(nn(result.authenticationToken.tokenString), NO, nil);
    }];
  });
}


// The code that returns a `nil` authentication token.
- (void)loginStatusWithBlock:(void(^)(FORLoginSourceLoginStatus *tokenStatus,
                                      NSString * _Nullable token, NSError * _Nullable error))block {
  auto _Nullable currentAuthenticationToken = FBSDKAuthenticationToken.currentAuthenticationToken; // Here I get `nil` even though the user has successfully logged-in in the previous session. 
  if (currentAuthenticationToken) {
    auto loginStatus = currentAuthenticationToken.lt_isActive ?
        $(FORLoginSourceLoginStatusLoggedIn) : $(FORLoginSourceLoginStatusLoginExpired);
    block(loginStatus, nn(currentAuthenticationToken.tokenString), nil);
  } else {
    block($(FORLoginSourceLoginStatusNotLoggedIn), nil, nil);
  }
}

// The code that enables getting the non-nil authentication token with the retry mechanism.
- (void)loginStatusWithBlock:(void(^)(FORLoginSourceLoginStatus *tokenStatus,
                                      NSString * _Nullable token, NSError * _Nullable error))block {
  __block uint attempt = 0;
  dispatch_queue_t queue = dispatch_queue_create("some queue", DISPATCH_QUEUE_SERIAL);

  __block void (^retryRetrieveFacebookAccessTokenBlock)(void) = [^{
    /// Works only after a few retries, approximately 4 retries in my case. 
    auto _Nullable currentAuthenticationToken = FBSDKAuthenticationToken.currentAuthenticationToken;
    if (currentAuthenticationToken) {
      /// Here I parse the JWT token to check if the token is expired or not.
      auto loginStatus = currentAuthenticationToken.lt_isActive ?
          $(FORLoginSourceLoginStatusLoggedIn) : $(FORLoginSourceLoginStatusLoginExpired);
      block(loginStatus, nn(currentAuthenticationToken.tokenString), nil);
    } else if (attempt < FORFacebookLoginSource.kMaxRetrieveFacebookAccessTokenRetryCount) {
      ++attempt;
      dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC));
      dispatch_after(delay, queue, retryRetrieveFacebookAccessTokenBlock);
    } else {
      block($(FORLoginSourceLoginStatusNotLoggedIn), nil, nil);
      return;
    }
  } copy];

  retryRetrieveFacebookAccessTokenBlock();
}

+ (uint)kMaxRetrieveFacebookAccessTokenRetryCount {
  return 20;
}
@tzuyangliu
Copy link

Same issue

@GalBerezansky
Copy link
Author

An update after updating to 17.0.2:

This issue persists. Have there been any updates or efforts made to resolve it? Currently, it is hindering our migration process. Thanks!

@GalBerezansky
Copy link
Author

Any update?

@satvicmovement
Copy link

17.0.3 same issue

@rjstech2020
Copy link

Facing same issue

@soumen-dev90
Copy link

FBSDKProfileDidChangeNotification is called yet token is not populated

@bobybacs
Copy link

facing the same issue and another problem is with the expiration date, which is usually 1 hour, so after that the user needs to login again to get a new authentication token

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants