Facebook Developers
DocsToolsSupportNewsApps
Log In
  • Social Plugins
  • Facebook Login
  • Open Graph
  • Facebook APIs
  • Games
  • Payments
  • App Center
  • Promote Your App
  • iOS
  • Android
  • JavaScript
  • PHP
  • More SDKs
  • Topics
    • Facebook SDK for iOS
  • Getting Started
    • Getting Started with the Facebook SDK for iOS
    • Build, Distribute and Promote
  • iOS SDK Tutorial
    • Facebook iOS SDK Tutorial
    • 1 - Authenticate Using Facebook Login
    • 2 - Personalize
    • 3 - Show Friends
    • 4 - Show Nearby Places
    • 5 - Publish Open Graph Story
  • Games Tutorial
    • iOS Games Tutorial
    • 1 - Authenticate
    • 2 - Personalize
    • 3 - Invites and Requests
    • 4 - Bragging and News Feed
    • 5 - Publish Open Graph Story
  • Upgrading SDKs Tutorials
    • Upgrading from 3.2 to 3.5
    • Upgrading from 3.1 to 3.2
    • Upgrading from 3.0 to 3.1
    • Upgrading from 2.0 to 3.1

1 - Authenticate Using Facebook Login

Documentation › Facebook iOS SDK Tutorial › 1 - Authenticate Using Facebook Login

This tutorial walks you through how to add Facebook login to your app with the Facebook SDK for iOS. Once you're done following these steps, your app will be able to authenticate people using it with the Facebook Login flow.

We start by introducing you to one of the Facebook SDK core objects: FBSession. Your app uses this object for authorization and to manage the Facebook login flow the app session. Any Facebook API calls that require authentication need to use FBSession. While an app can create instances of FBSession and manage them itself, FBSession provides helpers to simplify the common scenario of an app having a single logged-in person. We'll use those helpers here.

Here's the basic login/authorization flow:

  • Call the openActiveSessionWithReadPermissions:allowLoginUI:completionHandler: class method on the FBSession class, specifying the read permissions your app needs and providing a callback handler that will be notified of session changes in the future.
  • Handle the incoming link from the Facebook app.
  • Implement the successful login or error conditions in your open session callback handler.

This tutorial walks through the following:

  • Step 1: Set up the user interface
  • Step 2: Wire up the authentication logic
  • Step 3: Add the logout flow
  • Next steps
  • Related samples

The code comes from our Scrumptious sample iOS app.

Note: Before you start this tutorial, make sure you've set up your basic Facebook app.


Step 1: Set up the user interface

Our basic authentication flow involves two view controllers. The first one, SCViewController, will be active when a person is logged in. The second view controller, SCLoginViewController, will show up if the person is not logged in. The login view controller displays the login UI, initiates the authentication and passes control to SCViewController.

To get started with this, copy the image assets you'll use in the tutorial. Many of these assets appear in the login flow. The image assets can be found in the completed sample packaged with the Facebook SDK for iOS. They consist of images used in the app and app icon images. Images used in the app can be found in the images folder under ~/Documents/FacebookSDK/Samples/Scrumptious/scrumptious. Copy these by dragging the images folder into your Xcode project:

App icon images can be found under the ~/Documents/FacebookSDK/Samples/Scrumptious folder. Copy these images into your Xcode project.

Next, create a new view controller by right-clicking on the ''Scrumptious'' folder > New File > Objective-C class, and name the class ''SCLoginViewController''. Make sure to generate the corresponding NIB file as well:

Now, set up the SCLoginViewController.xib file as follows:

  • View: Change the main view's background color to 003366.
  • App Logo: Add an Image View object with the following properties: X, Y (offset): 20, 26; Width, Height (size): 74, 74; Image: Icon-72.png; Mode: center; Background: white
  • App Title: Add a Label object with the following properties: X, Y (offset): 107, 14; Width, Height (size): 193, 86; Text: ''Scrumptious''; Text font: Zapfino 28.0; Text color: 66CCFF;
  • Intro: Add a Label object with the following properties: X, Y (offset): 73, 137; Width, Height (size): 174, 59; lines: 0; Text: ''To get started, login using Facebook''; Alignment: center; Text color: FFFFFF;
  • Login Button: Add a Round Rect Button object. Center the button below the introductory text and modify the following properties: Title: ''Login''
  • Spinner: Add an Activity Indicator View object and center it under the login button. Modify the following properties: Hidden: YES; Hides When Stopped: YES.

Feel free to use your own colors and fonts. When you're done, your UI in Interface Builder should look like this:



Step 2: Wire up the authentication logic

Before wiring up the login flow, you should understand the flow you're implementing. Your app should initiate the login flow when a person taps the login button in the SCLoginViewController view. Once the person is successfully logged in, display the SCViewController. As a best practice, whenever the app starts, check for a previously stored session and show the logged-in UI for the app instead of the logged-out version.

For managing views, your main view controller will be SCViewController. Show the SCLoginViewController as a modal whenever you want to display the login UI. The app delegate contains most of the code that hands off control to the correct view controller.

With that background, let's get into the authentication logic.

Step 2a: Include the Facebook SDK

Open up the app delegate implementation file and include the Facebook SDK:

#import <FacebookSDK/FacebookSDK.h>

You can now reference the SDK functionality in your code.

Step 2b: Show the login view

Now in the app delegate implementation file, import the SCLoginViewController header:

#import "SCLoginViewController.h"

As you'll present the login view through a modal, SCViewController needs to be part of a UINavigationController. So, first define a private property for the new navigation controller by adding the following code before the SCAppDelegate implementation code:

@interface SCAppDelegate ()

@property (strong, nonatomic) UINavigationController* navController;

@end

Synthesize this new property:

@synthesize navController = _navController;

By default, Xcode creates a public property named viewController for the SCViewController instance. Let's rename this to mainViewController and make it private. To do this, first remove this declaration from the app delegate header file:

@property (strong, nonatomic) SCViewController *viewController;

Then, add a new SCViewController property in the app delegate private interface with the modified name:

@property (strong, nonatomic) SCViewController *mainViewController;

Next, modify the synthesized property to have the new name by changing:

@synthesize viewController = _viewController;

to:

@synthesize mainViewController = _mainViewController;

Then, make SCViewController the root view controller for this navigation controller. In the application:didFinishLaunchingWithOptions: method, change this code:

self.viewController = [[SCViewController alloc] 
                          initWithNibName:@"SCViewController" bundle:nil];
self.window.rootViewController = self.viewController;

to:

self.mainViewController = [[SCViewController alloc] 
                              initWithNibName:@"SCViewController" bundle:nil];
self.navController = [[UINavigationController alloc]
                         initWithRootViewController:self.mainViewController];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];

Now you can put the flow together. First, define a private method in the app delegate that shows the login view:

- (void)showLoginView 
{
    UIViewController *topViewController = [self.navController topViewController];

    SCLoginViewController* loginViewController = 
    [[SCLoginViewController alloc]initWithNibName:@"SCLoginViewController" bundle:nil];
    [topViewController presentModalViewController:loginViewController animated:NO];
}

Finally, in the application:didFinishLaunchingWithOptions: method, before the return statement check the Facebook session before displaying the correct UI:

// See if the app has a valid token for the current state.
if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
    // To-do, show logged in view
} else {
    // No, display the login page.
    [self showLoginView];
}

Build and run the project to make sure it runs without errors. You should see the login screen, but login button won't work yet. Next, you'll add logic to handle the button click and kick off the authentication flow.

Step 2c: Add the login action and handler

Wire up the SCLoginViewController UI so that when people click the login button, they're taken through the authorization flow. The UI you created includes a login button and an activity indicator. Attach the login button to an action to initiate the authorization flow. Then, attach the activity indicator to an outlet and animate it during the flow. The main logic for the authorization flow is in the app delegate file.

First, in SCLoginViewController.xib attach an action to the login button and call it performLogin. Next attach an outlet to the activity indicator and call it spinner. Add the action and outlet to the implementation file (not the header file):


You should now have an empty performLogin: method in the SCLoginViewController implementation file.

Now, switch to the app delegate implementation file. Define a public method openSession that will be called when someone clicks the login button. This method invokes the FBSession class method openActiveSessionWithReadPermissions:allowLoginUI:completionHandler: that initiates the authentication flow. The handler you define for the SDK authorization call, sessionStateChanged:state:error:, handles the success and error scenarios. It will also publish an app-wide notification when the session's state changes, so other parts of the app can react without hard-coding that dependency in the session state handler. Add these methods:

- (void)sessionStateChanged:(FBSession *)session 
                      state:(FBSessionState) state
                      error:(NSError *)error
{
    switch (state) {
        case FBSessionStateOpen: {
                UIViewController *topViewController = 
                    [self.navController topViewController];
                if ([[topViewController modalViewController] 
                    isKindOfClass:[SCLoginViewController class]]) {
                    [topViewController dismissModalViewControllerAnimated:YES];
                }
            }
            break;
        case FBSessionStateClosed:
        case FBSessionStateClosedLoginFailed:
            // Once the user has logged in, we want them to 
            // be looking at the root view.
            [self.navController popToRootViewControllerAnimated:NO];
            
            [FBSession.activeSession closeAndClearTokenInformation];
            
            [self showLoginView];
            break;
        default:
            break;
    }

    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc]
                     initWithTitle:@"Error"
                           message:error.localizedDescription
                          delegate:nil
                 cancelButtonTitle:@"OK"
                 otherButtonTitles:nil];
        [alertView show];
    }    
}

- (void)openSession
{
    [FBSession openActiveSessionWithReadPermissions:nil
                                       allowLoginUI:YES
                                  completionHandler:
                                       ^(FBSession *session, 
                                         FBSessionState state, NSError *error) {
                  [self sessionStateChanged:session state:state error:error];
    }];    
}

As a best practice, whenever a person opens the app, check for a cached session and go through a session check. You can call the openSession method to handle this. Modify the application:didFinishLaunchingWithOptions: method to add this call:

if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
    // Yes, so just open the session (this won't display any UX).
    [self openSession];
} else {
    // No, display the login page.
    [self showLoginView];
}

Now, add the openSession method to the app delegate header SCAppDelegate.h so it can be called from the login view controller:

- (void)openSession;

Next, switch to the login view controller implementation file, SCLoginViewController.m. Import the app delegate header so you can invoke the authorization methods you defined:

#import "SCAppDelegate.h"

Now add the following logic to the performLogin: method to implement login by calling the method in the app delegate file:

- (IBAction)performLogin:(id)sender 
{
    [self.spinner startAnimating];
    
    SCAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
    [appDelegate openSession];
}

If there is an issue during the authorization flow, for example if the person cancels it, you'll want to do some cleanup, like stopping the activity animation. To do this, define a login failed cleanup method:

- (void)loginFailed
{
    // User switched back to the app without authorizing. Stay here, but
    // stop the spinner.
    [self.spinner stopAnimating];
}

Declare this method in the SCLoginViewController header file so the app delegate can call it:

- (void)loginFailed;

If the login fails or is canceled, the person will see the login view through a call to the showLoginView defined in the app delegate file. To clean up any login flow UI like the spinner animation, modify the showLoginView method in the app delegate to call the loginFailed method in the SCLoginViewController view controller:

- (void)showLoginView 
{
    UIViewController *topViewController = [self.navController topViewController];
    UIViewController *modalViewController = [topViewController modalViewController];
    
    // If the login screen is not already displayed, display it. If the login screen is 
    // displayed, then getting back here means the login in progress did not successfully 
    // complete. In that case, notify the login view so it can update its UI appropriately.
    if (![modalViewController isKindOfClass:[SCLoginViewController class]]) {
        SCLoginViewController* loginViewController = [[SCLoginViewController alloc]
            initWithNibName:@"SCLoginViewController" 
                     bundle:nil];
        [topViewController presentModalViewController:loginViewController animated:NO];
    } else {
        SCLoginViewController* loginViewController = 
            (SCLoginViewController*)modalViewController;
        [loginViewController loginFailed];
    }
}

You now have most of the authorization logic complete. Next, you'll add logic to handle callback URLs from the Facebook app.

Step 2d: Handle the login with Facebook callback

During the Facebook login flow, your app passes control to the Facebook iOS app or Facebook in a mobile browser. After authentication, your app will be called back with the session information. In the app delegate, implement the application:openURL:sourceApplication:annotation: delegate method to call the Facebook session object that handles the incoming URL:

- (BOOL)application:(UIApplication *)application 
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication 
         annotation:(id)annotation 
{
    return [FBSession.activeSession handleOpenURL:url]; 
}

The flow back to your app may be interrupted, for example, if the person clicks the Home button if authenticating via the Facebook for iOS app. If this happens, the Facebook SDK can take care of any cleanup, which may include starting a fresh session. To enable this, in the applicationDidBecomeActive: delegate method call the active session's handleDidBecomeActive method:

// We need to properly handle activation of the application with regards to Facebook Login
// (e.g., returning from iOS 6.0 Login Dialog or from fast app switching).
[FBSession.activeSession handleDidBecomeActive];

Build and run the project to make sure it runs without errors. You should see the login screen. When you click the Login button, you should see the Permissions dialog. Once you authorize the app, you should see a blank screen.

Check that the session caching works correctly by stopping the app, ending any running sessions and relaunching the app. You should see the blank screen that signifies that a person is logged in.


Step 3: Add the logout flow

Next you should give people using your app a way to logout from Facebook and clear their session information. To do this, add a button to the main view controller and call a new method to take care of logout.

Open up the SCViewController.m file where you'll build the logged-in UI. Import the Facebook SDK header:

#import <FacebookSDK/FacebookSDK.h>

Next, create a new method that will close the current session and log a person out:

-(void)logoutButtonWasPressed:(id)sender {
    [FBSession.activeSession closeAndClearTokenInformation];
}

Next, add a logout button to the right bar of the navigation that calls the logoutButtonWasPressed: you defined. Add this logout button code at the end of the viewDidLoad method of SCViewController:

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] 
                                    initWithTitle:@"Logout"
                                    style:UIBarButtonItemStyleBordered
                                    target:self
                                    action:@selector(logoutButtonWasPressed:)];

Build and run the project to make sure it runs without errors. After login, your app should display a ''Logout'' button on the top right. When you click it, you should be taken back to the login view.


Next Steps

Learn how to personalize your app for someone who's logged in.


Related Samples

  • JustLoginSample
Updated about 2 weeks ago
Facebook © 2013 · English (US)
AboutAdvertisingCareersPlatform PoliciesPrivacy Policy