Posted on by

facebook-authSome developers encounter road blocks when they attempt to get Facebook working in their apps. Part of the challenge is trying to understand how Facebook authenticates users.

Corona’s facebook.login() API uses Facebook’s SDK to manage logins. All of the setup and execution to manage the oAuth 2.0 connections is handled automatically — you just need to provide some initial permissions and a listener function to handle the results from future Facebook calls. However, to achieve this simple access, there’s a lot of “behind the scenes” setup and several rules that you must understand.

Is the Native Facebook App Installed?

It’s important to understand the difference between when the Facebook app is installed or not installed. If your device has the native Facebook app installed, then the native app will launch to handle the login process. If the device does not have it installed, Facebook will open a web view to handle the login process.

The “web view process” is fairly simple and doesn’t cause too many issues. However, many developers struggle with the login process when the native app is installed.

Why do many developers struggle with the implementation when the native app is installed? Primarily, it’s due to how apps launch each other. In general terms, your app calls facebook.login() then it opens the native Facebook app. This pushes your app into the “background” and Facebook comes to the “foreground” to manage the login. When this occurs, Facebook needs a way to reactivate your app and bring it back to the foreground.

iOS Process

As of Corona SDK Build 2165 (2014.2165), Facebook for iOS was removed from the core and is now implemented via a plugin. If you’re using this build or later and you’re targeting iOS, you must include the following in the build.settings file.

settings = {

   plugins =
   {
      ["facebook"] =
      {
         publisherId = "com.coronalabs",
         supportedPlatforms = { iphone=true, ["iphone-sim"]=true }
      },
   },
}

For iOS, URL schemes are used to reactivate your app. Facebook tells iOS to launch an app that is “fbXXXXXXXXXXX” where “XXXXXXXXXX” is your Facebook AppID. To get this ID, configure the necessary aspects of your app in the Facebook Portal.  You must also provide the correct Bundle ID that matches the provisioning profile you are building with.  You cannot use the Wildcard ID here.

ios_fb

The actual AppID might look something like “2834883834838″. To make this work on the Corona side, you must add some code to your build.settings file.

settings =
{
   iphone =
   {
      plist =
      {
         UIApplicationExitsOnSuspend = false,
         FacebookAppID = "934738748374738",
         CFBundleURLTypes =
         {
            {
               CFBundleURLSchemes =
               {
                  "fb934738748374738",
               }
            }
         }
      },
   }, 
}

Notice that the Facebook AppID has to be in two locations. The CFBundleURLTypes block is how Facebook calls back to your app. In this field, remember to prefix the numerical value with fb, as in “fb934738748374738″. The other entry, FacebookAppID, is a recent change brought on by a newer SDK and it must be included in your app’s build.settings. With this in place, Facebook should be able to properly relaunch your app.

Android Process

As of Corona SDK Build 2431 (2014.2431), Facebook for Android was removed from the core and is now implemented via a plugin. If you’re using this build or later and you’re targeting Android, you must include the following in the build.settings file.

settings = {

   plugins =
   {
      ["facebook"] =
      {
         publisherId = "com.coronalabs"
      },
   },
}

For Android, the same basic behavior happens, except that Android launches apps based on the app’s Package Name. This must be properly configured in the Facebook Portal.

Android has a second requirement: you must provide the proper key hash in the developer portal to make sure the app is really your app. Previously, Facebook would tell you the key hash value it expects by outputting a line in your console log. Without this shortcut, however, you should know how to generate this value for Facebook.

As you may already know, when you deploy your apps to an Android store, you have to “sign” your app with a keystore. This is done by picking the keystore from the Corona SDK build screen — but before the keystore appears there, you must create it. The Android SDK provides you with a “debug” version, but you have to create your own keystore to release/publish the app to a store. You can use either of these for Facebook during testing, but once you release your app, Facebook requires the release keystore, not the debug version.

Instructions for creating the keystore can be found in our Signing and Building — Android Guide. It’s important to know that the keystore created with these instructions will be output to the folder you’re in when you run the command:

keytool -genkey -v -keystore mykeystore.keystore -alias aliasname -keyalg RSA -validity 999999

When you run this command, you should change the mykeystore.keystore portion to something appropriate for your app. Also, the aliasname should be changed to something less generic. You will be prompted for a password and the result will be a file named “mykeystore.keystore” (or whatever you named it) located in the directory that you’re in. This is important information when generating the keyhash for Facebook.

The instructions on Facebook’s site tell you to execute this command on Mac OS X

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

…or this command on Windows…

keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64

The problem with “blindly” executing these commands is that it makes assumptions that may not be correct for your setup! Let’s look at each of these:

  • -alias androiddebugkey — this assumes you want to use your “debug” keystore. If you want to use your release keystore, you have to change this to the correct alias.
  • -keystore ~/.android/debug.keystore — this should find an android debug.keystore but it won’t be the same debug keystore that Corona uses. On a Mac, the default debug.keystore is located in /Applications/CoronaSDK/Resource Library/Android. In addition, your release keystore may or may not have been stored in the ~/.android folder. Remember that it was created in the folder from which you ran the command. Thus, you should adapt this command line accordingly. It will prompt you for your password, which should be android for the debug keystore. On Windows, that command may work, but it’s unlikely that your release keystore is located in %HOMEPATH\.android.

If you’re using the debug.keystore, you need to specify the path to the Corona version.  If you are using a release version, you need to specify the path to your release version or be in the same folder.

Note that you can use Corona to find your keystore and alias. Just open up the Android Build dialog from within the Corona Simulator (File > Build > Android…). Your alias will show in one of the fields and the keystore with a path will show in the other:

coronafb1

If necessary, pull down on that field to see the full path:

coronafb2

Once you have this information, use the system’s “cd” command from the command line to change directory to that folder. From there, execute the keytool command like this, where yourkeyalias and yourkeystore.keystore are the names from the Corona build dialog box.

keytool -exportcert -alias yourkeyalias -keystore yourkeystore.keystore | openssl sha1 -binary | openssl base64

This will output the keyhash string to the Terminal/console. You can now copy that string and apply it to the proper field in the Facebook Portal.

android_fb

IAn easy way to obtain the key hash is from Facebook itself.  If you put in any incorrect key hash into the Facebook developer’s portal and try to run your app, Facebook will throw an error and print in your device’s console log the key hash it’s expecting from you.  Use:

adb logcat

and look for the error from Facebook.  You will see the hash key there, but it wont’ be formatted correctly.  You will need to copy the string from the log and change any hyphens “-” to a plus sign “+” and convert the underscore “_” to a front slash “/”.  You can then add this new key hash to the Facebook developer portal and change it.

That concludes this week’s tutorial. Hopefully we have “de-mystified” some of the setup issues that challenge many developers when integrating Facebook into their Corona apps.


Posted by . Thanks for reading...

14 Responses to “Understanding Facebook Authentication”

  1. Alan

    iOS has the option to sign into Facebook in the device’s settings app. The only thing I know it is used for is in game centre to like a game’s Facebook page.
    Is there any way to use this (presumably) device-wide login data to bypass the need to switch to the Facebook app/web view?
    It seems to me that is exactly what it’s purpose would be.

    Reply
  2. Rob Miracle

    Actually, iOS uses it in every place that you share something and you see the Facebook Icon along with Twitter, Email, Print, etc.

    I don’t know that apps that need to authenticate with Facebook can use that information, but if it can, Corona currently doesn’t support it. I don’t know of any apps that want to do things other than using the sharing dialog use it.

    Reply
  3. Axel Raymundo

    I’ve been struggling with this for awhile, I’ve done everything here for the android but it still gives me issues. When I clear my permissions from the Facebook developer portal, I can login just fine, it will ask me to authenticate the app and I can do everything normally. But when I logout, or try to login using another device, I keep getting the error ‘invalid android_key parameter. “The key xxxxxxx does not match any allowed key.” Again, if I just clear the permissions, it works fine. Using build 2013.1076 (2013.4.3)

    Any help would be greatly appreciated.

    Reply
    • Axel Raymundo

      I just solved it, I tried generating a key using the debug.keystore from Corona using the steps above but it gave me a different key compared to what appeared on the Facebook error which was JGn9F2vDQ_w6hexLxdefCUpxYIA. Naturally I tried using what appeared on the Facebook error, but it still didn’t work. I came across the key here http://docs.coronalabs.com/daily/guide/social/setupFacebook/index.html and saw that it was using a “/” instead of an “_” and tried and it worked! So my question here is why did my debug.keystore generate a different key, and why did the error output “_” instead of “/”? Hopefully this helped, I have yet to try this on a release keystore.

      Reply
  4. Michael Gartner

    Are you able to logout using facebook.logout()
    I have a multiuser app that I need to be able to log users out of. The native FB app always stays logged in for me.

    Reply
    • Rob Miracle

      I responded in your forum post. But for the benefit here, I needed to ask Michael some questions, but my understanding is that our facebook.logout() only logs the app out of facebook. The facebook app itself is still logged in with the user it was logged in with and it seems to remember previous permissions granted.

      Reply
    • Lance Adams

      The trick to logging out of Facebook is to do an invalid login.

      facebook.login( “0″, nil, {“publish_actions”,”user_birthday”} )
      facebook.logout()

      Unless the user signs out of Facebook, though, it will still remember the account, but it won’t automatically log in.

      Reply
  5. Haakon

    Will Corona support iOS 6 Native Login Dialog ?

    Will Corona support iOS 6 Native Login Dialog ?

    Will Corona support iOS 6 Native Login Dialog ?

    I’ve asked this question probably 20 times but no one seems to be willing to answer it. What’s up with this, why can’t we have the recommended way of logging in with Facebook implemented in Corona?

    Reply
    • Rob Miracle

      What do you mean by the iOS 6 Native Login Dialog? If you’re talking about apps using a share button to popup a dialog box, we just did a tutorial on that new plugin that was released last week.

      If you are talking about accessing those sharing credentials from your app somehow, I’m not sure that’s what the sharing controller does.

      Reply
      • MacDeep

        native.showPopup( “twitter”, options )

        Don’t you have something similar for “facebook”?

        Reply
  6. MagnoliaPower

    I am quite astonish to see how it is difficult for a crossplatform company to get a simple way to login, publish on a wall or in a photo album in facebook area. It is the same mess for livecode, phonegap, …

    we have here some part with built in functionalities, plugins, works around, … when shall we get something simple and straightforward ?

    Reply
  7. Dewey

    Rob…can you add something about the differences between test and production with Facebook.

    It’s not clear from the post above (or from this sentence: Facebook tells iOS to launch an app that is “fbXXXXXXXXXXX” where “XXXXXXXXXX” is your Facebook AppID.) where we should get the iPhone Store ID when we are testing prior to release…

    Thanks
    Dewey

    Reply
    • Rob Miracle

      The AppID here is the one that Facebook provides you when you create the app. The iPhone Store ID is the AppID from iTunes Connect which you can get from there. They are different numbers. You do not use the iPhone Store ID in your build.settings. Facebook uses this number so that when people click on your app links it will take them to your app. If you don’t have this number yet, you can either use the number of an existing app or 0.

      Rob

      Reply

Leave a Reply

  • (Will Not Be Published)