Facebook Authentication with Parse

My latest iOS application, Heart Quest, uses Facebook authentication and Parse for the back end. I ran into some challenges getting the two to work together but I am pleased with how my current implementation functions. I’d like to share that implementation here to help anyone who may be developing an app using Facebook authentication with their Parse apps.

NOTE: This will most likely be my only blog post related to Parse due to the service shutting down later this year. I have begun using Firebase as an alternative so look forward to some Firebase tutorials in the near future! 

If you still need to setup the Facebook SDK with your Parse app you can use the excellent guide over at Ray Wenderlich’s website. If you already have the Facebook SDK installed please continue with this tutorial.

To begin, initialize the FBSDK Login Manager and handle any errors:

let manager = FBSDKLoginManager()
manager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) -> Void in
if let error = error {
print(error.localizedDescription)
}

if result.isCancelled {
print("Cancelled")
} else {

logInWithReadPermissions is where you set the type of permissions you would like to request from your users. In the above example we are only asking the user for their basic profile information (name and profile picture). If you wanted to request additional permissions, such as the user’s Facebook likes, you would add that to the permissions array:

logInWithReadPermissions(["public_profile","user_likes"],

If there are no errors with logging in you’ll then want to check for any valid Facebook access tokens:

if let accessToken: FBSDKAccessToken = FBSDKAccessToken.currentAccessToken() {
PFFacebookUtils.logInInBackgroundWithAccessToken(result.token, block: {
(user: PFUser?, error: NSError?) -> Void in
if user!.isNew {
//segue to Sign Up form for a new user
} else {
//segue to first view for logged in users
}
if error != nil {
print("Uh oh. There was an error logging in.")

Use the .isNew method to check if that user has ever signed in to your app. This allows you to send new users to a separate Sign Up form so that you can save their user information in your database. If .isNew is false, use the else statement to send the logged-in user to your app.

If there is an error with the access token (error != nil), the best way to handle it is to create a new token and retry the login process:

let manager = FBSDKLoginManager()
manager.logOut()
manager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) -> Void in
if let error = error {
print(error.localizedDescription)
}

if result.isCancelled {
print("Cancelled")
} else {
//throw the new token into logInInBackgroundWithAccessToken(:)
if let accessToken: FBSDKAccessToken = FBSDKAccessToken.currentAccessToken() {
PFFacebookUtils.logInInBackgroundWithAccessToken(result.token, block: {
(user: PFUser?, error: NSError?) -> Void in
if user!.isNew {
//sign up new user
} else {
//segue to app
}
})
}
}
})

The final code for the Facebook Login button will then look something like this:

@IBAction func signin(sender: AnyObject) {

let manager = FBSDKLoginManager()
manager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) -> Void in
if let error = error {
print(error.localizedDescription)
}

if result.isCancelled {
print("Cancelled")
} else {

if let accessToken: FBSDKAccessToken = FBSDKAccessToken.currentAccessToken() {
PFFacebookUtils.logInInBackgroundWithAccessToken(result.token, block: {
(user: PFUser?, error: NSError?) -> Void in
if user!.isNew {
//segue to new user sign up form
} else {
//segue to app
}

if error != nil {
print("Uh oh. There was an error logging in.")

let manager = FBSDKLoginManager()
manager.logOut()
manager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) -> Void in
if let error = error {
print(error.localizedDescription)
}

if result.isCancelled {
print("Cancelled")
} else {
//new token is here and throw the token into logInInBackgroundWithAccessToken(:) again
if let accessToken: FBSDKAccessToken = FBSDKAccessToken.currentAccessToken() {
PFFacebookUtils.logInInBackgroundWithAccessToken(result.token, block: {
(user: PFUser?, error: NSError?) -> Void in
if user!.isNew {
//segue to new user sign up form
} else {
//segue to app
}
})
}
}
})
}
})
}
}
})
}

Leave a Reply

Your email address will not be published. Required fields are marked *