共用方式為


Using the Facebook iOS SDK for logging in to Azure Mobile Services

In my previous post I talked about how we can use the Facebook Android SDK to log in to Azure Mobile Services; continuing on with the topic, let’s look at the FB SDK for iOS projects.

Getting the Facebook iOS SDK

The first thing you need is the Facebook iOS SDK, which can be downloaded at the Facebook site. Like the version for Android, the “Getting Started” page in the Facebook docs for their iOS SDK is pretty good, with the steps required to both create the application on the Facebook Developers site. After downloading the package with the SDK and opening it, it will create a folder called FacebookSDK into your ~/Documents folder (unless you changed the location during install). At this point you should be able to open an iOS project in Xcode (either by creating a new one or using one which you want to add FB login support to). And you can add the Facebook SDK to your app by dragging the folder FacebookSDK.framework (located inside the FacebookSDK folder) into the Frameworks section of your iOS project.

Creating a Facebook App

Just like we had to do for Android, to use the Facebook SDK for login (and almost all other tasks) you need to create an application in the Facebook Developers portal. I’m assuming at this point that you already have a mobile service created, so I’ll skip that part. Once you log in to the developers portal, select the Apps menu, and then “Create a New App”. After entering the app name, the app will be created and you can select the “Settings” pane.

001-FacebookAppSettings

At the settings, select “Add Platform”, and select the iOS option. That will show a box similar to the one below. Until the app is submitted to the store, you can ignore the iPhone/iPad Store ID fields (the Facebook getting started page covers those). You’ll need, though, to set the bundle id (which you can see in Xcode by selecting the target), and set the “Single Sign On” toggle to “YES”.

002-FacebookAppiOSSettings

Once the app is set up on the Facebook developers portal, you can now connect it with your Xcode project. First, note the application id, shown on top of the Facebook app settings. Now open the file <projectname-Info.plist>, and add three values: “FacebookAppID” (string) with the value of the Facebook application id from the developers portal; “FacebookDisplayName” (string) with the display name configured in the portal; and “URL types” (array), with one element called “URL Schemes” (also typed array) with a single element, a string whose value is “fb” followed by the application id. Your plist file should resemble the image below (modulus the app id / name).

003-plistfile

At this point, the iOS app in Xcode is connected to the Facebook app, although it doesn’t do anything useful.

Using the Facebook login

The next step is to actually start using the login from the Facebook SDK. As with other parts of their SDK, Facebook did a good job in their tutorial (Login for iOS). There are two ways to implement login with the FB SDK, one with the FB login button, and the other using the FBSession object to login programmatically (via API calls). In this post I’ll cover the latter only. The Facebook doc goes in details about each step required so I’ll just mention them briefly here so I can get to the interaction with the mobile services login.

The minimal code changes we need are in two places: the app delegate, and the view controller which is handling the main app UI. First, in the app delegate class, we need to respond to the application:openURL:sourceApplication:annotation: selector so that when the app returns from the Facebook login dialog, it knows to return to the application. We also need to respond to the applicationDidBecomeActive: selector, which will handle the case of when the user presses the “home” button while a login operation is in progress. Finally, we should also change the application:didFinishLaunchingWithOptions: selector to see if we have a token from Facebook already in our application. This are the methods we need to implement:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded) {
[FBSession openActiveSessionWithReadPermissions:@[@"basic_info"] allowLoginUI:NO completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
NSLog(@"State changed: %@", session);
}];
}
return YES;
}

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

- (void)applicationDidBecomeActive:(UIApplication *)application
{
[FBAppCall handleDidBecomeActive];
}

Now on to the view controller. When we’re ready to log in, we retrieve the active session and make sure that it’s logged in. If that’s the case, then we can use that session object directly; otherwise we try to log in using the FB SDK (via the openActiveSessionWithReadPermissions:allowLoginUI:completionHandler: class method from FBSession), and if the login succeeded, we use the session object passed to it.

- (IBAction)clickMe:(id)sender {
FBSession *activeSession = [FBSession activeSession];
if (activeSession.state == FBSessionStateOpen || activeSession.state == FBSessionStateCreatedTokenLoaded) {
[self loginWithFBToken:activeSession];
} else {
[FBSession openActiveSessionWithReadPermissions:@[@"basic_info"] allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if ([session isOpen]) {
[self loginWithFBToken:session];
}
}];
}
}

Once we have a FBSession object which is open, we can request its access token, which is the piece of information which will finally allow us to log in to the Azure Mobile Service. With that, we create the JSON payload {"access_token":<the actual token>} and pass to the loginWithProvider:token:completion: selector of the MSClient class, as shown below.

- (void)loginWithFBToken:(FBSession *)session {
NSString *accessToken = session.accessTokenData.accessToken;
MSClient *client = [MSClient clientWithApplicationURLString:@"https://blog20140204.azure-mobile.net/" applicationKey:@"your-application-key-goes-here"];
    [client loginWithProvider:@"facebook" token:@{@"access_token":accessToken} completion:^(MSUser *user, NSError *error) {
if (error) {
NSLog(@"Error calling login: %@", error);
return;
}
NSLog(@"Logged in as %@", user.userId);
MSTable *table = [client tableWithName:@"item"];
NSDictionary *item = @{@"name":@"John Doe",@"age":@3};
[table insert:item completion:^(NSDictionary *item, NSError *error) {
if (error) {
NSLog(@"Error inserting item: %@", error);
return;
}
NSLog(@"Inserted: %@", item);
}];
}];
}

And that’s it. As with the Android version, I’ve found the Facebook SDK for login to be quite simple, and the singleton nature of the “active session” (along with the helper methods used in the app delegate implementation) makes coding for login with the native SDK a good choice for a better end-user login experience compared to the web-based login.

Comments

  • Anonymous
    January 06, 2015
    Carlos, great tutorial. I accomplished the Facebook login using the native iOS ACAccountStore and then passing the Facebook token to Azure Mobile Services. No Facebook API needed. However, when I tried the same technique for Twitter I get back the error: "POST of Twitter token is not supported". Any idea why Facebook works but Twitter does not? Is there a different format for passing the access token when calling loginWithProvider for Twitter?
  • Anonymous
    January 07, 2015
    This feature is currently not supported in the mobile services backend. I created a feature request at feedback.azure.com/.../4123328-add-support-for-client-side-twitter-authentication, please vote it up so that the team will prioritize it appropriately.
  • Anonymous
    January 07, 2015
    Got it. Thanks, will upvote.