37

I'm trying to transition my app to the new Facebook SDK 3.1 (with support for iOS6 authentication).

I had it working just fine, so I then decided to remove the app from my list of authorized apps on the FB website in order to test that iOS would ask for permission again.

Now my first call to [FBRequest requestForMe] causes this error:

Response:

{
  "error": {
    "message": "Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.",
    "type":"OAuthException",
    "code":190,
    "error_subcode":460
  }
}

Some details:

I'm trying to open the session as follows :

   [FBSession openActiveSessionWithReadPermissions:nil
                                       allowLoginUI:YES
                                  completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {

                                           switch (state) {
                                               case FBSessionStateOpen:
                                                   [self presentPostOptions];
                                                   break;

                                               case FBSessionStateClosed:
                                               case FBSessionStateClosedLoginFailed:
                                                   [FBSession.activeSession closeAndClearTokenInformation];
                                                   break;

                                               default:
                                                   break;
                                           }

I then get called back in state FBSessionStateOpen (at this point iOS hasn't presented a request dialog, is that to be expected)? Facebook logs this:

2012-09-26 13:43:43.768 MyApp[2177:907] FBSDKLog: FBSession INVALID transition from FBSessionStateCreated to FBSessionStateClosed
2012-09-26 13:43:43.769 MyApp[2177:907] FBSDKLog: FBSession transition from FBSessionStateCreated to FBSessionStateCreatedOpening 
2012-09-26 13:43:43.837 MyApp[2177:907] FBSDKLog: FBSession transition from FBSessionStateCreatedOpening to FBSessionStateOpen 

Once the session is open, in presentPostOptions I do this:

- (void)presentPostOptions
{    
    [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
        if (!error) {
            self.usersName = user.name;
            self.usersID = user.id;

            [self getPages];
        }
        else
        {
            [self didFailWithError:error];
        }
    }];
}

Before the above completion block is called back, my main state handler block is called with an FBSessionStateClosed state. In the meantime, the Facebook SDK has logged the above error.

I can't find any way to reset the system; nor do I really understand the cause.

Can anyone please shed some light?

Nikolay Fominyh
  • 8,946
  • 8
  • 66
  • 102
tarmes
  • 15,366
  • 10
  • 53
  • 87
  • 1
    i'm having the exact same issue as you described, just updated today to 3.1. even uninstalling the app does not help – Ultrakorne Sep 26 '12 at 12:36
  • I didn't try uninstalling because I specifically didn't want to do something that could potentially make it start working again :) I really want to find a programatic solution so that my users don't get stuck in this position. In any case, it's interesting to know that it doesn't solve the issue. – tarmes Sep 26 '12 at 13:03
  • Is this happening when you run in an iOS6 device/simulator only? Does it work on iOS5? – C Abernathy Sep 28 '12 at 02:18
  • 1
    Hi. This is happening on iOS6 running on a real device. I haven't tested on anything else at this stage. Note that it was working perfectly until I removed the app's permissions from Facebook, so I assume that this has left the iPhone's internal state in a mess, and I don't know how to reset it. It's frustrating to say the least - my users are waiting for an update. – tarmes Sep 28 '12 at 07:29
  • as tarmes stated same issue here in real device. on iOS5 it works because if you remove the app permission from Facebook you just need to reauthorize the app (so you get redirected to safari or fb app and you just have to allow the app again, as expected) – Ultrakorne Sep 28 '12 at 09:24
  • Have you tried to re-enable the app via device settings -> facebook? See this similar question: http://stackoverflow.com/questions/12620760/choosing-not-now-when-accepting-app-causes-com-facebook-sdk-error2 – borisdiakur Sep 28 '12 at 22:55

7 Answers7

76

The Facebook account on the device has become out-of-sync with the server as well as with the App's/SDK's cache. This can be solved by calling the ACAccountStore method renewCredentialsForAccount, which will update the OS's understanding of the token state.

In the next update of the SDK, the SDK will automatically call this API when it receives a response from the server indicating that a token has become invalid. For the 3.1.0 revision of the SDK, applications will need to explicitly call this API. Here is a code sample:

ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) &&
    (accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){

    NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
    id account;
    if (fbAccounts && [fbAccounts count] > 0 &&
        (account = [fbAccounts objectAtIndex:0])){

        [accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
            //we don't actually need to inspect renewResult or error.
            if (error){

            }
        }];
    }
}

There are several options for where/when to call the API. The simplest place would be to opportunistically make the call on application launch, or on view load. One problem with this approach is that it will cause a network round-trip that is often unnecessary. Another option is to call it when a session change notification occurs, indicating that a session has closed. Also many applications fetch some basic information such as graph.facebook.com/me, at application launch time, and if so -- a call to this method in case of an error response may be a reasonable place to ask iOS to update its token status.

Hopefully this helps!

Jason Clark
  • 1,343
  • 8
  • 8
  • Hi Jason. Thanks, I'll try that on Monday. Do you know when the next release of the SDK will be? – tarmes Sep 29 '12 at 21:17
  • 2
    We are working on a dot-release, with a limited number of bug fixes. It should not be too far out. – Jason Clark Sep 29 '12 at 23:31
  • Hi Jason. Having just updated the rest of my app for iOS 6 I now need to get the FB integration sorted out. I'd much rather use a bug free version of the SDK than add my own hacks :) Are you able to give some rough indication of the release date - are we talking days or weeks? Thanks. – tarmes Oct 02 '12 at 12:40
  • 1
    For info, I can confirm that this did fix the issue. Now I'm waiting for the SDK update so that this can be done in the right place. – tarmes Oct 03 '12 at 13:11
  • Here is the update (3.1.1) that fixes this directly in the SDK: https://github.com/downloads/facebook/facebook-ios-sdk/FacebookSDK-3.1.1.pkg Thanks!! – Jason Clark Oct 03 '12 at 21:45
  • That's great, thanks Jason. In the change log you note that "This does NOT address the 'code 2' errors from when ios6 users toggle the slider in their device Facebook settings though those cases do transition to 'ClosedLoginFailed' so it can be argued clients can code against it". What does this mean, and what should we be doing? – tarmes Oct 04 '12 at 08:14
  • Hi @tarmes, there is nothing you need to do special here. This comment is actually specifically targeted at the user-experience of the scrumptious sample -- and was meant to note that scrumptious is going to continue to blindly pop-up a message box for any FBErrorLoginFailedOrCancelled case. Sorry for the misleading comment. – Jason Clark Oct 04 '12 at 20:46
  • 2
    Hi Jason. I've installed the 3.1.1 and removed the temporary fix above. Unfortunately the new SDK doesn't fix the issue. I've tracked down the problem - can we discuss this somewhere? – tarmes Oct 05 '12 at 09:51
  • Hi @tarmes please email me or Facebook message me, and we can dig in a bit deeper on the problem. Thanks! – Jason Clark Oct 10 '12 at 03:55
  • OK, I've describe the problem and fix via FB message. Thx, Tim. – tarmes Oct 10 '12 at 08:10
  • @JasonClark, is there a method in the 3.1.1 SDK that does what your code chunk above does? I am using that code to fix an account-switching "code 2" error and was wondering whether I can call it somewhere or have to create my own function. – ill_always_be_a_warriors Oct 12 '12 at 16:17
  • Unfortunately still a problem for me using 3.1.1. When I log the `fbAccounts` array, all I get is an empty field. Annoyingly, I also accidentally selected "Don't Allow" on one of the dialogs and now I don't see any alerts at all... It just fails silently :( – jowie Nov 16 '12 at 10:51
  • 1
    @JasonClark - I'm using 3.1.1 and experiencing a variety of related issues with this. One specific case is if the user removes their FB account from iOS settings the app/SDK still believe they have a valid token. And the token MAY be valid, but it seems wrong to continue using it if the user removed their account from Settings. And what if they then add a different FB account in iOS Settings - the app has no way of knowing to pick that up and use it instead of the cached session it has. – TomSwift Nov 26 '12 at 17:41
  • I'm also getting this error after removing the app from my facebook account. When trying to fix, the fbAccounts array has nothing in it. Ideas? – dizy Nov 30 '12 at 17:45
  • I just updated to SDK 3.2, still have this problem.... (tested on ios6.0 iphone5) – minovsky Mar 04 '13 at 10:19
  • Can anyone explain why "we don't actually need to inspect renewResult or error"? – Kaigi May 29 '13 at 05:38
  • 1
    Still have this problem on SDK 3.7.1 – jjxtra Sep 12 '13 at 21:55
7

I'm just going to contribute another thing to check that caused me to waste 3 hours: Make sure your FB app settings do not have the 'Sandbox' option on if you're trying to login with a non-app-developer FB user... Maybe obvious, but could save others a few hours hopefully.

snowdragon
  • 753
  • 7
  • 18
4

Try adding, if you haven't already, your iOS App Bundle ID in the settings panel of your Facebook APP as suggested here.

Hope this helps.

Cyupa
  • 1,126
  • 13
  • 37
1

I'm fairly sure this is a Facebook iOS SDK bug (even on 3.1.1) and I filed this bug report.

While trying to reproduce this bug using their sample app Scrumptious, I found that it allows you to successfully re-authorize if you are using openActiveSessionWithReadPermissions. However, if you are asking for publish permissions via openActiveSessionWithPublishPermissions, it would be stuck in com.facebook.sdk.error 5.

honk
  • 9,137
  • 11
  • 75
  • 83
Min Kim
  • 39
  • 1
  • 4
  • I didn't read the [documentation](https://developers.facebook.com/docs/tutorial/iossdk/upgrading-from-3.0-to-3.1/) carefully. You have to call openActiveSessionWithRead first, then write. It looks like you can't start with openActiveSessionWithPublishPermissions.. – Min Kim Oct 19 '12 at 08:24
1
[FBSession openActiveSessionWithReadPermissions:nil
 allowLoginUI:YES
 completionHandler:^(FBSession *session, FBSessionState  state, NSError *error) 
    {

       switch (state) {
           case FBSessionStateOpen:
               [self presentPostOptions];
               break;

           case FBSessionStateClosed:
           case FBSessionStateClosedLoginFailed:
               [FBSession.activeSession closeAndClearTokenInformation];
               break;

           default:
               break;
       }

      }];   
SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
0

In facebook SDK 3.7.1 I still had this issue. Basically I have decided to clear the token from the facebook cache when this happens. Like this:

if(state == FBSessionStateClosed ) {
     [FBSession.activeSession closeAndClearTokenInformation];
}
Tiago Almeida
  • 14,081
  • 3
  • 67
  • 82
0

Simple Swift 2+ Solution for Facebook Error Validating Access Token

// Step 1: Logout 
FBSDKLoginManager().logOut()

// Step 2: Login
FBSDKLoginManager().logInWithReadPermissions(["public_profile", "email"], fromViewController: self, handler: { result, error -> Void in 

// ...

}

If this error occurs, you have to create new Facebook Session, so you have to login again.

fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88