Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Facebook Login Dialog does not work on iOS6 simulator

I have been converting my application from the old Facebook SDK to the new Facebook SDK 3.1 in order to use the iOS6 native functionality as well as other Facebook functionality, and I am having a problem that happens consistently on the simulator and rarely on the device.

When I go to log into Facebook, instead of the app backgrounding and authenticating through Safari or the Facebook app, I get a modal window on top of my app for the login (I believe this started with iOS6, even before switching to Facebook SDK 3.0/3.1). This window allows me to enter username and password, but when I go to click "Okay" in the upper right to authenticate, nothing happens. No callback occurs to the application:openURL:sourceApplication:annotation: in the AppDelegate.

Facebook Login

In my shared FacebookController code (which I use for multiple projects), I am initializing the FBSession when attempting to authorize as per Facebook's sample code:

FBSession *session = [[FBSession alloc] initWithAppID:nil permissions:readPermissions defaultAudience:FBSessionDefaultAudienceNone urlSchemeSuffix:self.fbUrlSchemeSuffix tokenCacheStrategy:nil];

if(session.state == FBSessionStateCreated || session.state == FBSessionStateCreatedTokenLoaded)
{
  [FBSession setActiveSession:session];

  // we open after the fact, in order to avoid overlapping close
  // and open handler calls for blocks
  [session openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
...

The code for the completion handler is never executed unless I click the x cancel button on the dialog (in which case I get an error as expected).

I am setting the FacebookAppID in my iOS target properties (info.plist) and I have the URL Schemes set up with fb###[url_scheme_suffix] as well.

The only difference I have between my code and the Facebook sample code is that I am using url scheme suffixes as I have a free and paid version of our app.

If the app uses Safari to log in, it works with the code as given. If it fast-switches to the Facebook app, it also works. Additionally, the shared facebook ios6 account settings work. The app only fails if it uses the in app modal.

Has anyone else encountered this?

like image 771
Peter Nolen Avatar asked Oct 03 '12 16:10

Peter Nolen


1 Answers

The same thing is happening to me. It only occurs on the simulator (iphone5 4 inches, ios6), so I don't know if this issue will be present in actual devices.

After a couple of debugging sessions, i found that the FBDialog's webView:shouldStartLoadWithRequest:navigationType: method was not processing a url that was carrying the access_token. When facebook passes the access_token, it means you are authenticated. So, I figured, there was something missing there.

Here is the shape of the url that is not being processed:

fb122222222222222://authorize/#access_token=...&expires_in=5102464&code=...

Note that the url scheme is the same fb+API Key you have configured in the Info.plist file in your app.

Here is what I did in order to fix this issue. Note that I added a new else-if branch, in which I call the dialog success in case we have the access token:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
 navigationType:(UIWebViewNavigationType)navigationType {
    NSURL* url = request.URL;

    if ([url.scheme isEqualToString:@"fbconnect"]) {
        if ([[url.resourceSpecifier substringToIndex:8] isEqualToString:@"//cancel"]) {
            NSString * errorCode = [self getStringFromUrl:[url absoluteString] needle:@"error_code="];
            NSString * errorStr = [self getStringFromUrl:[url absoluteString] needle:@"error_msg="];
            if (errorCode) {
                NSDictionary * errorData = [NSDictionary dictionaryWithObject:errorStr forKey:@"error_msg"];
                NSError * error = [NSError errorWithDomain:@"facebookErrDomain"
                                                      code:[errorCode intValue]
                                                  userInfo:errorData];
                [self dismissWithError:error animated:YES];
            } else {
                [self dialogDidCancel:url];
            }
        } else {
            if (_frictionlessSettings.enabled) {
                [self dialogSuccessHandleFrictionlessResponses:url];
            }
            [self dialogDidSucceed:url];
        }
        return NO;
    }
//THIS IS WHAT I'VE ADDED>>>>
        else if ([[[[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"] firstObject] objectForKey:@"CFBundleURLSchemes"] firstObject] isEqual:url.scheme])
        {
            [self dialogDidSucceed:url];
            return NO;
        }
//<<<<<
    else if ([_loadingURL isEqual:url]) {
        return YES;
    } else if (navigationType == UIWebViewNavigationTypeLinkClicked) {
        if ([_delegate respondsToSelector:@selector(dialog:shouldOpenURLInExternalBrowser:)]) {
            if (![_delegate dialog:self shouldOpenURLInExternalBrowser:url]) {
                return NO;
            }
        }

        [[UIApplication sharedApplication] openURL:request.URL];
        return NO;
    } else {
        return YES;
    }
}

I is worth mentioning that i am following all the fb sdk guidelines (3.1) and I havent made any further changes to the src code.

With those changes, the fb login process works as expected.

I hope this helps!

like image 135
Lio Avatar answered Nov 16 '22 14:11

Lio