Facebook login using the iOS API with Swift

A common requirement for consumer mobile apps is to allow users to authenticate with their FaceBook credentials. Let’s explore why, and then go ahead and make the integration with iOS and Swift

Why use Facebook authentication?

Why would we want to use Facebook auth instead of providing our own authentication database? Really it boils down to two reasons:

  1. Easier user experience. If we let users use their Facebook accounts to authenticate to our application, they don’t need to remember a new user id and password, and are more likely to go ahead and use our app because it’s a frictionless experience.
  2. Easier and more secure for our app. Since we’re effectively “outsourcing” identity to Facebook, we don’t need to manage/secure user passwords, implement password reset processes and so on.

Overall Process

Here’s the overall process of integrating Facebook Identity:

  1. Register our app on Facebook. This lets Facebook know who we are, when authentication requests come to their API. In the setup process we’ll also communicate which Facebook services we’re going to use. Some of the services we can integrate into our app require additional Facebook review of us. But the basic authentication in this post does not.
  2. Integrate the Facebook API into our XCode project. Just like any integration, we’ll need to add some frameworks. In this project I’ll be using CocoaPods to download and install the Facebook frameworks.
  3. Add a button to the app UI to initiate the Facebook request. This can be done in code or in storyboard design. I’ll use the storyboard method.
  4. Capture the Facebook user ID, and insert it into our own web service database so we can associate the Facebook users with one of our users.

Register with Facebook

Facebook provides a Quick Start for iOS tool to create app IDs, which I’ll be using.

  1. On the Quick Start form, provide a display name for the new App, adn then click on the Create New Facebook App ID button.
  1. The next step is to provide a contact e-mail and an application category. After providing this info, click the Create App ID button.
  1. From here, the Facebook Quick Start screens are providing us some great step-by-step instructions what to do next. Capture the information about the info.plist contents, which we’ll later add to our app.
  1. Mid-way down this form is a switch to indicate whether the app we’re creating contains in-app purchases. The default is Yes, so if your app doesn’t include them (or if you don’t want to use FB to track them), slide this button to the No position.

Finally — and this may be the most important step! — provide the Bundle Identifier for the app to Facebook. When our app makes calls to the FB API, it will send the Bundle ID, which FB will use to match our app to the App ID record we just created within FB.

Adding the Facebook API to our XCode Project

Next up, we need to add the Facebook API to our XCode project. This can be done by downloading the Facebook frameworks and manually integrating them, but I always find using CocoaPods more productive and a better way to keep 3rd-party modules up-to-date over time.

Install CocoaPods

If you’re not familiar with CocoaPods, it’s a Ruby-based package manager that modifies your XCode project to include 3rd-party modules (like the Facebook API). CocoaPods will configure an XCode workspace that includes your project, and additional projects for the 3rd-party components.

If you don’t have CocoaPods installed on your development workstation, or don’t know what it is, browse over to https://cocoapods.org to learn about it and install it before continuing.

Create the Podfile

After creating your base XCode project, open a bash shell in the same folder where your .xcodeproj is located, and then run the following command to create a new Podfile

$ pod init

Next edit the Podfile (I’m using nano, but you can use any text editor). Update the new Podfile to look as follows:

At this point, your project folder should look something like this:

After updating the Podfile, make sure XCode is closed, and then run a the following command to download the Facebook frameworks and configure your XCode workspace:

$ pod install

Once the frameworks are installed and the .xcworkspace is created, your folder should now look like this:

From this point, you should never have a reason to open your .xcodeproj project, and from now on always open the .xcworkspace file instead. The Facebook API frameworks will be new projects in the workspace, referenced by your original project while editing and building the project.

Back in step 1, Facebook gave us text to add to our .plist file, so open the .xcworkspace, and then open the .plist file as text (so we can paste in the entries FB gave us).

Add the entries from the Facebook Quick Start screen before the closing </dict> tag.

Setup the AppDelegate

Two methods to update int he AppDelegate class. The first is our old friend application : didFinishLaunchingWithOptions. In this method, just add a call to pass on the launch parameters to the Facebook API:

FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)

Next, add the delegate method application : open url, and fill it out with a similar call that passes on to Facebook API:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let sourceApplication: String? = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: sourceApplication, annotation: nil) }

With these changes, the AppDelegate will make calls to the Facebook API when initially launched (didFinishLaunchingWithOptions method), and when launched after the Facebook login is completed (open url method).

Configure the UI

Since this is a test application, I’ve created it as a simple single view app. In the default storyboard, I’ve added the following controls:

  • A UIView in the shape of a button, with the class name set to FBSDKLoginButton, connected to a class outlet named loginButton
  • A UIView in the shape of a square profile photo, with the class name set to FBSDKProfilePictureView. No class outlet is needed.
  • A UILabel, with a class outlet named userIdLabel
  • A UILabel, with a class outlet named userNameLabel

In the storyboard, the form looks like so:

Add code to the ViewController

There’s not much code involved in making this login button work. Its presence on the form is enough to enable it. The code we add really is just to set a couple properties, and add delegate methods that are called as the user interacts with the Facebook login process.

Add the Import

import FBSDKLoginKit

Declare our class with the delegate protocol

class ViewController: UIViewController, FBSDKLoginButtonDelegate {

Connect Outlets

@IBOutlet weak var loginButton: FBSDKLoginButton! @IBOutlet weak var userIdLabel: UILabel! @IBOutlet weak var userNameLabel: UILabel!

Configure the button

In the ViewDidLoad method, add the following configuration lines:

loginButton.delegate = self loginButton.readPermissions = ["public_profile", "email", "user_friends"] FBSDKProfile.enableUpdates(onAccessTokenChange: true)
  • The first line sets this ViewController as the delegate for the Facebook login events
  • The second line lets the FB login process know what read permissions we’re asking the user to approve
  • The third line asks the SDK to send a notification if/when the user’s profile changes.

Create a profile change listener

Just below the button configuration lines, add the following code to receive a notification when the user’s profile is updated (asynchronously) after the login completes.

NotificationCenter.default.addObserver( forName: NSNotification.Name.FBSDKProfileDidChange, object: nil, queue: nil) { (Notification) in if let profile = FBSDKProfile.current(), let firstName = profile.firstName, let lastName = profile.lastName { self.userNameLabel.text = "(firstName) (lastName)" } else { self.userNameLabel.text = "Unknown" } }

The listener is needed because the profile won’t be completely populated at the moment the login completes. So effectively this code will wait around for the API to complete the profile, then will be called.

After the user interacts with Facebook to login, we’ll be notified when the login is completed, and if the user presses the button again to logout.

func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let result = result { self.userIdLabel.text = result.token.userID // Notify our web API that this user has logged in with Facebook } } func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) { print("Logging out") }

With these methods implemented, the application is complete.

If using Simulator, Turn Keychain Sharing on

If you don’t need to test using a simulator, and will use a physical device for testing, proceed to the next section — you’re good to go.

However, if you want to run this application on a simulator and connect to Facebook, there’s one more small thing to do — enable Keychain Sharing for your target.

Select your target, and in the Capabilities tab, slide the Keychain Sharing switch to the “On” position. Similar to the below (image credit:

Running the application

When we run this application, the first thing we see is the main form, with the login button waiting to be pressed:

After pressing the login button, the application will be put in background while Safari launches to ask the user to login within the Facebook mobile experience. In this screen I’m informed that I’ve already authorized this app once, so I only have to confirm that I still want to login.

After I finish with Facebook, I’m transferred again back to AppDelegate, within that open url method we implemented earlier. Afterward, the form is shown again, this time with my profile photo, name and Facebook ID.

And that’s it!

Leave a Reply

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