Tuesday, October 30, 2012

Facebook Login


Facebook Login

Facebook Login for iOS allows you to obtain an access token to access Facebook services on behalf of a user. You can use this feature in place of building your own account system or to add Facebook services to your existing accounts.
Facebook Login với iOS cho phép bạn obtain một access token để truy cập Facebook services với tư cách là một người dùng. Bạn có thể sử dụng những tính năng trong place of building your own account system hay để thêm Facebook serviecs đến những tài khoản đã tồn tại.
Click here...
Today there are three ways a user can login to Facebook. Originally using Facebook Login in your iOS app would show an in-app web view where the user could connect. In late 2010 we introduced a faster technique called Single Sign On, or SSO, that enabled one-click access for user using the native Facebook for iOS app. In iOS 6, Apple is introducing Facebook integration built into iOS directly, which further simplifies the process.
Hôm nay có 3 cách để người sử dụng có thể đăng nhập vào Facebook. Cách truyền thống là sử dụng Facebook Login trong iOS app, nó sẽ show một in-app web view mà ở đó người dùng có thể connect. Sau năm 2010 chúng tôi đã giới thiệu một kỹ thuật nhanh hơn được gọi là Single Sign On, hay SSO, điều này cho phép one-click access cho người dùng bằng cách sử dụng native Facebook for iOS app. Ở iOS 6, Apple đang giới thiệu sự tích hợp Facebook được xây dựng trực tiếp trong iOS, tương lai nó sẽ làm đơn giản hoá quá trình.
The Facebook SDK for iOS will automatically choose the best option when you attempt to use Facebook login. If a user previously gave your app permissions, the SDK will immediately return an OAuth 2 access token back to your app, possibly without even showing the user a prompt. For this reason, we recommend you always use the Facebook SDK for iOS to obtain Facebook access tokens.
Facebook SDK cho iOS sẽ tự động chọn tuỳ chọn tốt nhất khi bạn cố găng sử dụng Facebook login. Nếu một người dùng trước đây gave your app permissions, SDK sẽ ngay lập tức reuturn một OAuth 2 access token back to app của bạn, possibly without even hiển thị user a prompt. Vì lý do này, chúng tôi khuyên bạn luôn luôn sử udngj Facebook SDK cho iOS để obtain Facebook access tokens.
This article walks through the following topics:

Login Setup

In order to use Facebook Login you will first need to add the Facebook SDK to your project. The next few steps will help you through that. If you have already added the Facebook SDK to your project, skip to step 4.
Để sử dụng Facebook Login đầu tiên bạn sẽ cần add the Facebook SDK đến dự án của bạn. Một vài bước tiếp theo sẽ giúp bạn through that. Nếu bạn đã add Facebook SDK đến dự án của bạn, hãy bỏ qua bước 4.

Step 1: Get Started

Follow the Getting Started with the iOS SDK document to get up and running on the basics. Follow the steps in that guide to complete the following tasks:
  • Install the Prerequisites
  • Install the Facebook iOS SDK
  • Create a Facebook App

Step 2: Set Up your Xcode Project

The Getting Started with the iOS SDK document has a ''Start a new Xcode Project'' section that walks you through setting up your Xcode project for Facebook integration. If you have an existing Xcode project, you can skip over the step that asks you to create a new project. Follow all the other steps in that section.
The Getting Started với iOS SDK document có một phấn là "Start a new Xcode Project"  mà walks you through setting up dự án Xcode của bạn cho sự tích hợp Facebook. Nếu bạn có một dự án Xcode đã tồn tại, bạn có thể skip over bước này mà yêu cầu bạn tạo một dự án mới. 

Step 3: Include the Facebook SDK

In your app delegate header, add code to include the Facebook SDK:
#import <FacebookSDK/FacebookSDK.h>

Step 4: Implement the Login Flow

The flow involves adding a login button that when clicked initiates Facebook Login. The FBSession class has properties you use to open and check the state of the Facebook session object. The FBSession method that handles opening the session can be passed a completion handler that can be used to detect session changes. We will make use of notifications to broadcast session changes that your classes can then use to control their UI.
Những dòng dưới đây bao gồm việc thêm một nút login mà khi click nó sẽ khởi tạo Facebook Login. The FBSession class có những thuộc tính mà bạn sử dụng để mở và kiểm tra trạng thái của đối tượng Facebook session. Phương thức FBSession nó sẽ xử lý việc mở session có thể được truyền một completion handler mà có thể được sử dụng để phát hiện ra session đã thay đổi. Chúng tôi sẽ dùng notifications để broadcast session changes mà những lớp của bạn có thể sau đó sử dụng để điều khiển UI của chúng.
First, add a button to your view controller and set up the button to initiate the login flow. Let's assume that you wired this button to an action method called authButtonAction:.
Đầu tiên, add một button đến your view controller và thiết lập button để khởi tạo login flow. Bạn phải nối button này đến một action method được gọi là authButtonAction:
Next, open up your app delegate header file and define a global variable that is used for notifications:
extern NSString *const FBSessionStateChangedNotification;
Then open up your app delegate implementation file and define the notification string:
NSString *const FBSessionStateChangedNotification =
    @"com.example.Login:FBSessionStateChangedNotification";
You should make the notification string unique. For example, you can change com.example.Login to your app's Bundle Identifier.
Bạn nên tạo notification string là duy nhất. Ví dụ, bạn có thẻ thay đổi com.example.Login đến app's Bundle Identifier.
Next, open up your app delegate implementation file and add two methods. The first method calledopenSessionWithAllowLoginUI: is invoked when the login button is clicked or when a check is made for an active session when the main view is initially loaded. This method calls theopenActiveSessionWithReadPermissions:allowLoginUI:completionHandler: method of FBSession class to open a Facebook session. The second method called sessionStateChanged:state:error: defines the completion handler. The completion handler for the session open method handles all the session state change functions, including checking the authorization callback and monitoring any subsequent session state changes. Add these two new methods:
Tiếp theo, mở file app delegate implementation của bạn và add 2 phương thức. Phương thức đầu tiên được gọi là openSessionWithAllowLoginUI:  được gọi khi button login được click hoặc khi một check được tạo cho một active session khi main view được initially loaded. Phương thức này gọi  phương thức openActiveSessionWithReadPermissions:allowLoginUI:completionHandler: của lớp FBSession để mở một Facebook session. Phương thức thư 2 được gọi là sessionStateChanged:state:error: định nghĩa completion handler. Completion handler for session mở method handles all the session state change functions, bao gồm việc kiểm tra authorization callback và giám sát bất kì subsequent session state bị thay đổi. Thêm 2 method mới:
/*
 * Callback for session changes.
 */
- (void)sessionStateChanged:(FBSession *)session
                      state:(FBSessionState) state
                      error:(NSError *)error
{
    switch (state) {
        case FBSessionStateOpen:
            if (!error) {
                // We have a valid session
                NSLog(@"User session found");
            }
            break;
        case FBSessionStateClosed:
        case FBSessionStateClosedLoginFailed:
            [FBSession.activeSession closeAndClearTokenInformation];
            break;
        default:
            break;
    }
    
    [[NSNotificationCenter defaultCenter]
     postNotificationName:FBSessionStateChangedNotification
     object:session];
    
    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Error"
                                  message:error.localizedDescription
                                  delegate:nil
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
        [alertView show];
    }
}

/*
 * Opens a Facebook session and optionally shows the login UX.
 */
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
    return [FBSession openActiveSessionWithReadPermissions:nil
                                          allowLoginUI:allowLoginUI
                                     completionHandler:^(FBSession *session,
                                                         FBSessionState state,
                                                         NSError *error) {
                                         [self sessionStateChanged:session
                                                             state:state
                                                             error:error];
                                     }];
}
Now, add the openSessionWithAllowLoginUI: to the app delegate header file, so your view controller can invoke it:
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI;
If you want to ask for additional permissions, modify the FBSession initialization in theopenSessionWithAllowLoginUI: method. For example, to ask for email and user_likes permissions, use the following code:

Nếu bạn muốn thêm những permission thì chỉnh sửa khai báo FBSession trong openSessionWithAllowLoginUI: method. Ví dụ, để thêm email và user_likes permissions, sử dụng code sau:
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
    NSArray *permissions = [[NSArray alloc] initWithObjects:
        @"email", 
        @"user_likes",
        nil];
    return [FBSession openActiveSessionWithReadPermissions:permissions
                                              allowLoginUI:allowLoginUI
                                         completionHandler:^(FBSession *session,
                                                         FBSessionState state,
                                                         NSError *error) {
                                         [self sessionStateChanged:session
                                                             state:state
                                                             error:error];
                                     }];
}
You can only ask for read permissions when opening the session. If you need write permissions, ex: publish_actionsthen you would call the reauthorizeWithPermissions:defaultAudience:completionHandler: method in theFBSession class. As a best practice you should ask for write permissions in context, so it is clear to the user why you are requesting that access. As an example, you would ask for publish_actions when the user chooses to publish an action to their timeline. Refer to the permissions guide for more information on permissions.
The login flow differs if the user is using iOS6+ or earlier OS versions. For pre iOS6, during the login flow, your app will pass control to the Facebook iOS app or Facebook in mobile Safari. After the user authenticates, control will pass back your app with the session information in a specially encoded URL. To properly record this information, you need to give the Facebook SDK a chance to process incoming URLs. In iOS6+, the login flow gets the user's credentials from iOS and the user is not transitioned to the Facebook app. The Facebook SDK takes care of these interactions under the hood and all you have to do is call the required FBSession methods.
In the app delegate, implement the application:openURL:sourceApplication:annotation: delegate method to call the Facebook session object:
/*
 * If we have a valid session at the time of openURL call, we handle
 * Facebook transitions by passing the url argument to handleOpenURL
 */
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    // attempt to extract a token from the url
    return [FBSession.activeSession handleOpenURL:url];
}
The flow back to your app may be interrupted (for ex: if the user clicks the Home button if authenticating via the Facebook for iOS app). If this happens, the Facebook SDK can take care of any cleanup that may include starting a fresh session. To enable this, in the applicationDidBecomeActive: delegate method call the active session'shandleDidBecomeActive method:
// We need to properly handle activation of the application with regards to SSO
// (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
[FBSession.activeSession handleDidBecomeActive];
You should also take care of closing the session if the app is about to terminate. Do this by adding the following code to the user applicationWillTerminate: app delegate method:
[FBSession.activeSession close];
Now that you have set up the authentication code in the app delegate, go back to your view controller implementation file to invoke the authentication methods. First, include the app delegate header file:
#import "AppDelegate.h"
Next, in the authButtonAction method fill out the implementation to invoke the openSessionWithAllowLoginUI:method you defined in the app delegate:
- (IBAction)authButtonAction:(id)sender {
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    // The user has initiated a login, so call the openSession method
    // and show the login UX if necessary.
    [appDelegate openSessionWithAllowLoginUI:YES];
}
Build and run the project. When the login button is clicked, you should see something like this:

You should also see an NSLog showing that a valid user session has been found:
2012-08-10 18:02:24.529 TestLogin[47133:c07] User session found
Once you've verified the login flow, you can remove the NSLog statement in the sessionStateChanged:state:error:method defined in your app delegate implementation file.
You'll notice that even though you've logged in the login button is still labeled ''Login''. You'll take care of this in the next step.

Step 5: Implement the Logout Flow

For simplicity, we we'll assume you'll use the same button for logging the user in and out. Add an outlet named ''authButton'' to the login button you set up previously. Use this to control the button text when the user is logged in versus logged out.
Now, set up a new method in the app delegate implementation file that handles logging out:
- (void) closeSession {
    [FBSession.activeSession closeAndClearTokenInformation];
}
Next, add this new method to the app delegate header file:
- (void) closeSession;
Now, make the following changes to your view controller. Modify the authButtonAction: method to detect the session validity and log the user in or out:
- (IBAction)authButtonAction:(id)sender {
    AppDelegate *appDelegate =
        [[UIApplication sharedApplication] delegate];
    
    // If the user is authenticated, log out when the button is clicked.
    // If the user is not authenticated, log in when the button is clicked.
    if (FBSession.activeSession.isOpen) {
        [appDelegate closeSession];
    } else {
        // The user has initiated a login, so call the openSession method
        // and show the login UX if necessary.
        [appDelegate openSessionWithAllowLoginUI:YES];
    }


}
Then, in the viewDidLoad method, register for the session change notification you defined in the app delegate by adding this code to the end of the method:
[[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(sessionStateChanged:)
     name:FBSessionStateChangedNotification
     object:nil];
Unregister for the notifications by adding the following code to the end of the didReceiveMemoryWarning the method:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Next, define a new private method sessionStateChanged: to change the button text:
- (void)sessionStateChanged:(NSNotification*)notification {
    if (FBSession.activeSession.isOpen) {
        [self.authButton setTitle:@"Logout" forState:UIControlStateNormal];
    } else {
        [self.authButton setTitle:@"Login" forState:UIControlStateNormal];
    }
}
Finally, modify the viewDidLoad method to show the logged in versus logged out button by calling the app delegateopenSessionWithAllowLoginUI: method to check for a cached token. While checking the cached token, you are setting a flag to open a session while avoiding a login UI flow. Add this code to the end of the method:
// Check the session for a cached token to show the proper authenticated
// UI. However, since this is not user intitiated, do not show the login UX.
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate openSessionWithAllowLoginUI:NO];
Build and run the project. Since the session should be active from your first run, the button should be set to ''Logout''.
Click on the button to log out the user. The button text should change to ''Login''. Clicking the button again should switch you to the Facebook app (iOS or mobile Safari) and show you an interstitial screen with an ''OK'' button. We'll talk about how to get rid of this interstitial screen in the Best Practices section.

Best Practices

Pro-tip 1: Include Facebook Login at User Registration

Apps often only use Facebook Login when asking the user to enable Facebook features in the app. You should also include Facebook Login anywhere you prompt the user to register for your app, which usually shows up the first time a user launches an app. Users can enjoy a simplified registration process and you can request the same information that you would normally collect manually (ex: email address).

Pro-tip 2: Request Only the Permissions Your App Needs

Because so much personal information is stored by users in Facebook, we have a very extensive permission system to protect their privacy. In particular, certain permissions (called extended permissions) are shown separately to the user during login, where they are given an opportunity to opt-out of them individually.
In general, you will get the best login rate from users if you only request the permissions you need to register them and use your basic features. If you need additional permissions later, you can always request them at a time when the user is better informed about your app and why you might need them.
More information about our privacy system can be found in this blog post.

Pro-tip 3: Do not request offline_access or publish_stream

In the past, using Facebook services when a user was not actively interacting with your application required a special permission called 'offline_access'. This permission is no longer required and will soon be deactivated.
If you have an older application that was using this permission you can learn more about how to upgrading access tokens.
Also, many apps incorrectly ask for 'publish_stream' to add content to a user's News Feed. This permission tends to hurt conversion for your users and is almost never needed. Instead, consider publishing Open Graph actions or using our Feed Dialog - which does not require this permission.

Pro-tip 3: Complete all iOS App Settings

Fill out every field related to your app in the Native iOS App section of the Basic Settings in the App Dashboard. If these fields are not configured, we can't drive traffic to your app or the iOS App Store.
In addition, we use the iOS Bundle ID to streamline authentication for users who already authenticated your app.