Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handler does not get called after Facebook Browser Login redirects to Application

I am using Facebook SDK v4.8.0 for iOS in my application for login with Facebook. (iPhone OS version 9.3)

Following is some related code for integration:

AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
    return true
}

func applicationDidBecomeActive(application: UIApplication) {
    FBSDKAppEvents.activateApp()
}

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {    
        return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}

func application(application: UIApplication, openURL url: NSURL, options: [String: AnyObject]) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url,
                                                                     sourceApplication: "UIApplicationOpenURLOptionsSourceApplicationKey",
                                                                     annotation: "UIApplicationOpenURLOptionsAnnotationKey")
}

Login.Swift

@IBAction func btnFacebook(sender: UIButton) {

    self.loginToFacebookWithSuccess({ (response) -> Void in
        print("Success")
    }) { (error) -> Void in
        print("failure")
    }

func loginToFacebookWithSuccess(successBlock: () -> (), andFailure failureBlock: (NSError?) -> ()) {

    let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
    fbLoginManager.loginBehavior = .SystemAccount

    FBSDKLoginManager().logInWithReadPermissions(["public_profile", "email", "user_friends"], fromViewController: self, handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in

        if error != nil {
            print("error")
        } else if result.isCancelled {
            print("cancelled")
        } else {
            print("worked fine") // get Facebook user data here
        }
    })
}

When the user has not configured Facebook account in the device, the App goes to browser and provides Facebook login UI. Once, the user is done with login the Browser redirects to the App. Till this point everything works fine.

Problem

When the browser redirects the user to App, nothing happens. (No handler for success OR failure is called). Just in case of user taps on "Done" in the browser, "cancelled" is printed in log. But, for "cancel" or "okay" (or say "Continue as Username") nothing happens after redirection.

Any clue?

Let me know, if I have missed any information.

like image 542
viral Avatar asked May 14 '16 12:05

viral


3 Answers

I think your open url method needs following change:

func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool {

    let isFBURL = ((url.scheme?.hasPrefix("fb\(FBSDKSettings.appID()!)"))! && url.host == "authorize")

    if  isFBURL == true {

        return FBSDKApplicationDelegate.sharedInstance().application(application, open: url,
                                                                     sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
                                                                     annotation: options[UIApplicationOpenURLOptionsKey.annotation] as? String)
    }
}

Let me know, if it works.

like image 104
sweta.me Avatar answered Nov 15 '22 16:11

sweta.me


I'd recommend use Facebook approach and implement their FBSDKLoginButton. Set read permissions to the button facebookButton.readPermissions = ["email", "user_birthday", "public_profile"]. And the delegate to the viewController.

//MARK:- FBSDKLogin Button Delegate
extension LoginViewController: FBSDKLoginButtonDelegate {

    func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {

        guard let response = result, let _ = response.token else {
            createAlertController("Error", message: "There was a problem with the Facebook login. Please try again.")
            return
        }

        //Do what ever you need here
    }

    func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
        //Required method, we don't need it at login screen
    }
}

Make sure you follow all the Facebook plist settings information. And App Transport Security for iOS 9+

like image 38
Marcos Griselli Avatar answered Nov 15 '22 15:11

Marcos Griselli


In the application(application: UIApplication, openURL url: NSURL, options: [String: AnyObject]) method you are passing in the sourceApplication and annotation parameters hardcoded strings.

I think that this is the issue. Try to pass the values that are in the options dictionary with the static keys UIApplicationOpenURLOptionsSourceApplicationKey and UIApplicationOpenURLOptionsAnnotationKey.

You also should need to add @available(iOS 9.0, *) before the method declaration because it's only available from iOS 9.

The final function should be something like this:

@available(iOS 9.0, *)
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
   return FBSDKApplicationDelegate.sharedInstance().application(app, openURL: url, sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as! String, annotation: options[UIApplicationOpenURLOptionsAnnotationKey])
}
like image 27
tx2 Avatar answered Nov 15 '22 15:11

tx2