问题
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?
回答1:
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!
回答2:
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.
回答3:
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.
回答4:
[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;
}
}];
回答5:
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
.
回答6:
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];
}
回答7:
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.
来源:https://stackoverflow.com/questions/12601191/facebook-sdk-3-1-error-validating-access-token