Facebook SDK 3.1-验证访问令牌时出错



我正在尝试将我的应用程序转换到新的Facebook SDK 3.1(支持iOS6身份验证)。

我让它运行得很好,所以我决定将该应用程序从FB网站上的授权应用程序列表中删除,以测试iOS是否会再次请求许可。

现在,我对[FBRequest requestForMe]的第一次调用导致以下错误:

响应:

{
"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
}
}

一些细节:

我正试图以如下方式打开会话:

[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;
}

然后,我在状态FBSessionStateOpen下被召回(此时iOS还没有显示请求对话框,这是意料之中的事吗)?Facebook记录此:

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 

一旦会话打开,在presentPostOptions中我这样做:

- (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];
}
}];
}

在调用回上面的完成块之前,我的主状态处理程序块是用FBSessionStateClosed状态调用的。与此同时,Facebook SDK已经记录了上述错误。

我找不到任何重置系统的方法;我也不了解原因。

谁能给我点光吗?

设备上的Facebook帐户与服务器以及应用程序/SDK的缓存不同步。这可以通过调用ACAccountStore方法renewCredentialsForAccount来解决,该方法将更新操作系统对令牌状态的理解。

在SDK的下一次更新中,当SDK收到来自服务器的指示令牌无效的响应时,它将自动调用此API。对于SDK的3.1.0版本,应用程序需要显式调用此API。这是一个代码示例:

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){
}
}];
}
}

关于在何处/何时调用API,有几个选项。最简单的方法是在应用程序启动或视图加载时机会主义地进行调用。这种方法的一个问题是,它将导致经常不必要的网络往返。另一个选项是在会话更改通知发生时调用它,指示会话已关闭。此外,许多应用程序在应用程序启动时会获取一些基本信息,如graph.facebook.com/me,如果是这样,则在出现错误响应时调用此方法可能是要求iOS更新其令牌状态的合理位置。

希望这能有所帮助!

我只想贡献另一件事来检查一下,这件事让我浪费了3个小时:如果你试图使用非应用程序开发人员FB用户登录,请确保你的FB应用程序设置没有打开"沙盒"选项。。。也许很明显,但希望能为其他人节省几个小时。

如果您还没有,请尝试按照此处的建议在Facebook应用程序的设置面板中添加您的iOS应用程序捆绑包ID。

希望这能有所帮助。

[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;
}
}];   

我很确定这是一个Facebook iOS SDK错误(甚至在3.1.1上),我提交了这个错误报告。

当我试图使用他们的示例应用Scrumptius重现这个错误时,我发现如果你使用openActiveSessionWithReadPermissions,它可以让你成功地重新授权。但是,如果您通过openActiveSessionWithPublishPermissions请求发布权限,它将被困在com.facebook.sdk.error 5中。

在facebook SDK 3.7.1中,我仍然有这个问题。基本上,我已经决定在发生这种情况时从facebook缓存中清除令牌。像这样:

if(state == FBSessionStateClosed ) {
[FBSession.activeSession closeAndClearTokenInformation];
}

用于Facebook错误验证访问令牌的简单Swift 2+解决方案

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

如果发生此错误,您必须创建新的Facebook会话,因此您必须再次登录。

相关内容

最新更新