ibm-bluemix-mobile-services/bms-clientsdk-swift-security-facebookauthentication

BMSFacebookAuthorization and Sample App readme documentation Incomplete

Closed this issue · 1 comments

My Problem

Following the readme, I discovered that the most important part was missing... How do you login to Facebook? The readme only talks about initial setup in the app delegate. From here my thought process was to try out the sample app.

I downloaded the sample app, added my bluemix route/guid and facebook app id stuff. Got it to compile, went to click on the connect with facebook button and no facebook login happened. Upon further inspection I noticed that the connect with facebook button only invokes a rest call to the bluemix route url + guid.... And then just prints out the HTML of that page.

So I looked at the readme that came with the sample app and it says the following:

a GET request is made to a protected resource in the Node.js runtime on Bluemix. This code has been provided in the MobileFirst Services Starter boilerplate. The Node.js code provided in this boilerplate must be present in order for the sample to work as expected.

Confused why I would need to add Node.JS code? The old IMFFacebookAuth stuff never needed to do that. It instead opened a web browser that allowed me to login to facebook and then once I did it kicked me back to my app. The readme doesn't provide any more information about what this Node.js code is supposed to look like or where I can specifically find it.

My Solution:
Luckily I had code left over from the previous time I used IMFFacebookAuthorization so I was able to modify the old code to work with BMSFaceBookAuthorization. I used this code and got it to successfully log me into Facebook. Here is that code.

/**
     Method to get authentication token from Facebook SDK

     - parameter callback: Success or Failure
     */
    func getAuthToken(callback : ((networkRequest: NetworkRequest) -> ())) {

        //let authManager = IMFAuthorizationManager.sharedInstance()
        // authManager.obtainAuthorizationHeaderWithCompletionHandler( {(response: IMFResponse?, error: NSError?) in



        let authManager = BMSClient.sharedInstance.authorizationManager
        authManager
        authManager.obtainAuthorization(completionHandler: {(response: Response?, error: NSError?) in
            let errorMsg = NSMutableString()

            //error
            if let errorObject = error {
                callback(networkRequest: NetworkRequest.Failure)
                errorMsg.appendString("Error obtaining Authentication Header.\nCheck Bundle Identifier and Bundle version string\n\n")
                if let responseObject = response {
                    if let responseString = responseObject.responseText {
                        errorMsg.appendString(responseString)
                    }
                }
                let userInfo = errorObject.userInfo
                errorMsg.appendString(userInfo.description)
            }

                //no error
            else {
                if let identity = authManager.userIdentity {
                    if let userID = identity.id  {
                        if let userName = identity.displayName {

                            //save username and id to shared instance of this class
                            self.fbUniqueUserID = userID as String
                            self.fbUserDisplayName = userName as String

                            //set user logged in
                            self.isLoggedIn = true

                            //save user id and name for future app launches
                            NSUserDefaults.standardUserDefaults().setObject(userID, forKey: "user_id")
                            NSUserDefaults.standardUserDefaults().setObject(userName, forKey: "user_name")
                            NSUserDefaults.standardUserDefaults().synchronize()


                            print("Got facebook auth token for user \(userName) with id \(userID)")

                            self.checkIfUserExistsOnCloudantAndPushIfNeeded()

                            callback(networkRequest: NetworkRequest.Success)
                        }
                    }
                    else {
                        print("Valid Authentication Header and userIdentity, but id not found")
                        callback(networkRequest: NetworkRequest.Failure)
                    }

                }
                else {
                    print("Valid Authentication Header, but userIdentity not found. You have to configure one of the methods available in Advanced Mobile Service on Bluemix, such as Facebook")
                    callback(networkRequest: NetworkRequest.Failure)
                }


            }

            })

    }

Why isn't this code mentioned at all in the readme?

The sample code describes a request made to a protected resource. In order for it to work you need your Bluemix to:

  1. Add MCA service to your Bluemix app.
  2. Configure MCA to use Facebook authentication.
  3. Have an end-point in your Bluemix app which is protected using passport. You can follow
    these instructions

The way the authorization process works is that the Facebook authentication is triggered by the client trying to access a protected resource on the server. If you are trying to reach a non-existent resource, (as you are, if you are using the sample app without having a proper back-end in Bluemix), Facebook authentication will not be triggered.

Another way to trigger the authorization process is to manually call "obtainAuthorizationHeader" which is what the code you added does.