Handle invalid accessToken with FBSession openActiveSessionWithReadPermissions in Facebook iOS 3.1.1 SDK

14,471

The questions you linked are relevant, especially Facebook SDK 3.1 - Error validating access token which explains the problem where the Facebook account on the device is out of sync with the server (I.e., if you deleted the app from App Center). As mentioned there, in 3.1.1 the SDK will call to renew the device token only when it gets the invalid response from the server. This is a trade off in convenience for less round-trips to the server.

Assuming your code block is executed on applicationDidFinishLaunching or something similar, it will go to the else block because the app starts with a new session. When it calls openActiveSessionWithReadPermissions, the iOS 6 device thinks the token is valid and will let the state go to Open, so then your "do something" gets executed. Only then does the SDK get the invalid response from the server and invalidate the device token. As a result, the next time the procedure is called, it will prompt the user appropriately to authorize again.

This is intentional. For now, you can consider a automatic retry in your application if the error code describes an invalid token. For example, see the Scrumptious sample postOpenGraph retry code. In your case, it may look closer to something like (I used requestForMe as the "do something" for demonstration purposes):

else {
    [FBSessionopenActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
        if(FB_ISSESSIONOPENWITHSTATE(status)) {
            //do something
            [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
                if (!error){
                    NSLog(@"success on first try");
                } else if ([[error userInfo][FBErrorParsedJSONResponseKey][@"body"][@"error"][@"code"] compare:@190] == NSOrderedSame) {
                    //requestForMe failed due to error validating access token (code 190), so retry login
                    [FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
                        if (!error){
                            //do something again, or consider recursive call with a max retry count.
                            NSLog(@"success on retry");
                        }
                    }];
                }
            }];
        }
    }];
}
Share:
14,471
ozzotto
Author by

ozzotto

coeliac. madridista. developer.

Updated on June 19, 2022

Comments

  • ozzotto
    ozzotto almost 2 years

    Before anything, I have read both this and this questions to solve the problem below and before asking.

    My problem is that when the accessToken gets expired (either because the expiration date passes, or manually by deleting the app from my Facebook's App Center) the following code:

    if ([[FBSession activeSession] isOpen]) {
            //do something
        }
    else {
            [FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
                if(FB_ISSESSIONOPENWITHSTATE(status)) {
                    //do something
                }
              }
           }];
         }
    

    gets in the else block with FBSession.activeSession open but when the 'do something' is executed the accessToken is invalid so the request gets Error: HTTP status code: 400. When I try to do the whole procedure twice immediately the FBSession asks for permission (either UIAlertView for iOS6 integrated facebook, Facebook App or Facebook website in Safari) and the rest runs smoothly.

    My concern is why I have to do everything twice to work well and why Facebook SDK cannot detect in the first time that the activeSession and accessToken are invalid.

    Thank you all in advance!

  • ozzotto
    ozzotto over 11 years
    Thank you very much Chris! It seems to work, though not with a second retry but with the fourth one. I assume it will be something fixed in a next SDK update.
  • MaxGabriel
    MaxGabriel over 11 years
    The approach to getting the error code doesn't seem to reliably work. I think the JSON format isn't consistent: Error Domain=com.facebook.sdk Code=5 "The operation couldn’t be completed. (com.facebook.sdk error 5.)" UserInfo=0x12c81710 {com.facebook.sdk:ParsedJSONResponseKey=( { body = { error = { code = 190; message = "The access token was invalidated on the device."; type = OAuthException; }; }; code = 400; } ), com.facebook.sdk:HTTPStatusCode=400}
  • MaxGabriel
    MaxGabriel over 11 years
    -[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance