Ranknoodle Ranknoodle - 2 months ago 27
iOS Question

iOS Swift Facebook Authentication with Google Firebase - How to pull extra permissions?

Im using the latest version for Facebook SDK 4.15 and and Google Firebase to authenticate users. I'm following along the documentation here: https://firebase.google.com/docs/auth/ios/facebook-login

This is working for me.

However I would like to pull extra permissions like email from the Facebook user. I have modified the code like so:

@IBOutlet var facebookButton : FBSDKLoginButton!


override func viewDidLoad() {
/...
facebookButton.readPermissions = ["email","public_profile"]
...
}


With this I get the Facebook confirm dialog asking for email permission when authorizing my app through Facebook. So that works.

However on my callback the user's email address is always nil:

func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError?) {
if let error = error {
print(error.localizedDescription)
return
}

let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
// ...
if let error = error {
print(error.localizedDescription)
return
}

print("user.uid \(user!.uid)")
print("user.photoURL \(user!.photoURL)")
print("user.providerID \(user!.providerID)")
print("user.email \(user!.email)")
print("user.displayName \(user!.displayName)")


How can I pull the extra permission like email through Facebook login while using Google Firebase Authentication?

Answer

When using third party authentication, you get back an authentication token which you then use to sign a user into your app. With this token, Firebase Auth is able to extract the user's email address along with it. But for your case, if you're looking to getting the user's email address after FB logging in, you'd need to use Facebook's Graph API. You simply have to make a GraphRequest containing the info you're asking for as shown below.

Swift 2

struct FacebookPermission
{
    static let ID: String = "id"
    static let NAME: String = "name"
    static let EMAIL: String = "email"
    static let PROFILE_PIC: String = "picture"
    static let LAST_NAME: String = "last_name"
    static let FIRST_NAME: String = "first_name"
    static let USER_FRIENDS: String = "user_friends"
    static let PUBLIC_PROFILE: String = "public_profile"
}

func getFacebookData()
{
    let graphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "\(FacebookPermission.NAME), \(FacebookPermission.FIRST_NAME), \(FacebookPermission.LAST_NAME), \(FacebookPermission.EMAIL), \(FacebookPermission.PROFILE_PIC).type(large)"])

    graphRequest.startWithCompletionHandler { (connection: FBSDKGraphRequestConnection!, result:AnyObject!, error: NSError!) in

        if error == nil
        {
            if let userName = result.valueForKey(FacebookPermission.NAME) as? String
            {
                self.currentUser.userName = userName
            }

            if let firstName = result.valueForKey(FacebookPermission.FIRST_NAME) as? String
            {
                self.currentUser.firstName = firstName
            }

            if let lastName = result.valueForKey(FacebookPermission.LAST_NAME) as? String
            {
                self.currentUser.lastName = lastName
            }

            if let email = result.valueForKey(FacebookPermission.EMAIL) as? String
            {
                self.currentUser.email = email
            }

            if let profilePic = result.valueForKey(FacebookPermission.PROFILE_PIC)
            {
                let facebookImageURL = profilePic.valueForKey("data")?.valueForKey("url") as? String

                if let unwrappedURL = facebookImageURL
                {
                    let imageData: NSData = NSData(contentsOfURL: NSURL(string: unwrappedURL)!)!
                    self.currentUser.profileImage = UIImage(data: imageData)!
                }
            }
        }
        else
        {
            print("Facebook Graph Request Error")
        }
    }
}

Swift 3

func getFacebookData()
{
    let graphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "\(FacebookPermission.NAME), \(FacebookPermission.FIRST_NAME), \(FacebookPermission.LAST_NAME), \(FacebookPermission.EMAIL), \(FacebookPermission.PROFILE_PIC).type(large)"])

    graphRequest.start { (connection: FBSDKGraphRequestConnection?, result: Any?, error: Error?) in

        if error == nil
        {
            if let facebookData = result as? NSDictionary
            {
                if let userName = facebookData.value(forKey: FacebookPermission.NAME) as? String
                {
                    self.currentUser.userName = userName
                }

                if let firstName = facebookData.value(forKey: FacebookPermission.FIRST_NAME) as? String
                {
                    self.currentUser.firstName = firstName
                }

                if let lastName = facebookData.value(forKey: FacebookPermission.LAST_NAME) as? String
                {
                    self.currentUser.lastName = lastName
                }

                if let email = facebookData.value(forKey: FacebookPermission.EMAIL) as? String
                {
                    self.currentUser.email = email
                }

                if let profilePic = facebookData.value(forKey: FacebookPermission.PROFILE_PIC)
                {
                    let facebookImageURL = ((profilePic as AnyObject).value(forKey: "data") as AnyObject).value(forKey: "url") as? String

                    if let unwrappedURL = facebookImageURL
                    {
                        let imageData: Data = try! Data(contentsOf: URL(string: unwrappedURL)!)
                        self.currentUser.profileImage = UIImage(data: imageData)!
                    }
                }
            }
        }
        else
        {
            print("Facebook Graph Request Error")
        }
    }
}

After grabbing their info you may go ahead and store it into your Firebase Database.

Here's more info about Facebook Permission. Cheers mate!