There seems to be near universal misunderstanding of Facebook’s Android SDK and the single sign on (SSO) feature Facebook added late last year. I originally wrote a response on Stack Overflow detailing the fix but I didn’t realize the connection to SSO at the time. I’m hoping this post can summarize the problem and solutions for the mass of similarly confused developers who get stuck here.
In November 2010, Facebook announced that they’re enabling Single Sign On in the Android SDK. Applications that take advantage of this feature will allow users to skip re-entering credentials and dive right into the action. What they do not mention is that SSO isn’t a feature developers opt into, it’s actually on by default. However, it only changes the way the Facebook SDK works IF the Facebook application is also installed. This causes the problem that most developers (including myself) see when they first set out to build an application.
The typical description of the problem goes something like this: You’ve downloaded the SDK and your application is running perfectly with shiny new Facebook authentication on the Android emulator. But when you deploy it to a device, it no longer works. The app loads but the Facebook login dialog disappears instantly. If you’re more familiar with Android development than I was at the start, you start up your copy of adb logcat while your application is running and you see logs that look something like this:
D/Facebook-authorize( 2194): Login failed: invalid_key
W/System.err( 2194): com.facebook.android.FacebookError: invalid_key
At this point, you Google for solutions to the issue and quickly start pulling out your hair out at the number of people reporting this issue with no apparent fix. The problem is actually very simple, though not immediately obvious. The problem is that, when deploying your application to the device after developing on the emulator, you’ve inadvertently and implicitly enabled Single Sign On because your device has the Facebook application installed. This is why one of the reported fixes is to uninstall the Facebook application. Your emulator does not have the Facebook application installed (though the Facebook SDK includes it if you want to install it), but your device does, thus triggering the SSO code. And SSO has some special configuration requirements that non-SSO does not which causes the invalid_key error above.
Fixing the Issue
There are a few different ways to tackle this problem.
1. The ugly: Uninstall the Facebook app
Don’t do this. You’re not going to be able to ask your users to do the same anyway. The only reason this works is because the SSO functionality is triggered by the presence of the Facebook application and this simply removes the possibility of using SSO completely, which is also a crappy user experience.
2. The bad: Opt-out of Single Sign On
If you want, you can actually have your application skip SSO completely. You probably don’t want to do this, but it’s a reasonable solution if you’re convinced you do. To do so, you need to modify the code calling Facebook to specify that you want to handle auth on your own. You do this by passing FORCE_DIALOG_AUTH value into the authorize method’s activityCode parameter.
3. The good: Set up Single Sign On properly (recommended)
Unless you have a good reason not to, you should set up SSO. It’s a bit more work, but it’s the best experience for your users.
Buried in the Facebook documentation is a mention about hash codes. Although it’s not obvious in the documentation, Single Sign On requires applications to provide a Key Hash or certificate (I use them interchangeably) of the signature used to sign the application to Facebook. This is used as part of the validation with SSO. When applications are built by the Android development tools, they’re automatically signed using a debug keystore. You need to use this keystore to generate the certificate. Details about the Debug keystore are available in the Android Documentation – Signing Applications.
In order to provide Facebook with information about the signature, you need to pull it from the keystore. On OSX, you do this in the terminal with the following command:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
This generates a short string of characters (which may include characters such as ‘=’ or ‘/’) that identify the signature. This is the certificate or Key Hash as Facebook calls it. Once you have this, you need to give it to Facebook.
Find your application on Facebook’s Developer page (or create a new one if you haven’t set one up already). Once you’re in the application summary page, choose ‘Edit’ on the Settings banner and then pick ‘Mobile’ on the left-hand side. Under the Android section, you’ll see a box for Key Hash. Paste the certificate string from the command above into this box and hit save. Give it a few minutes to propagate and try running your application again. The invalid_key errors should disappear. Keep in mind, when you sign your application for distribution, you’ll have to generate another certificate like you do here and provide that as well.
SSO isn’t completely smooth sailing though, there are a few issues to watch out for.
1. authorize() always shows a page, even if the user is authorized
As far as I’m concerned, this is a bug in the SDK. The workaround is to store the token after authorizing the first time and simply use that instead of calling authorize again while isSessionValid() is true (Stack Overflow has a great example of how to save the access_token using Android’s PreferenceManager). However, unless you want to request an offline_access token, the token will only be valid every 24 hours.
2. Different Access Token formats
The token received from SSO applications are of a different format. There’s a bug open on Facebook’s bug tracker about this, but they can’t seem to track it down despite it being easy to replicate. This isn’t a huge issue, but unfortunately, you won’t be able to parse the user ID of the Facebook User out of the SSO token the way you can from standard access token format
3. UI is inconsistent between SSO and non-SSO
Non-SSO uses a nicer pop-over dialog to show the authentication panel while the SSO panel slides in from the right (and back out to the right after the user finishes). There doesn’t appear to be a way to change this UI, at least without hacking the SDK code directly.