CS and the City

by Sean Lynch

TwitterGithub

Android, the Facebook SDK, SSO, and You

July 1, 2011

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.

Background

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 issue

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 Weirdities

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.

36 responses

  • Peter on July 1, 2011

    It is a long time since I looked at the Facebook integration in my my app but it does suffer from ” authorize() always shows a page, even if the user is authorized”, is this really avoidable? I tried to follow the examples in the SDK but they seem to suffer from it too. I really wish it was simple adding 2 or 3 lines of code to login.

  • Sean Lynch on July 1, 2011

    It’s only avoidable by storing the access_token until it expires (which, currently, is 24 hours unless you’re requesting offline_access).

  • Peter on July 2, 2011

    24 hours is not really all that long and offline access is a scary sounding permission (to me anyway).
    Sso is broken if you ask me but Facebook ignored the bug I saw open about it. I imagine Android will have some amazing Google + integration in a little while.

  • Leiko on August 16, 2011

    Thank you so much. You just save my day.

  • blogeton on August 16, 2011

    gracias pero no es lo que busco

  • Rashmi B on August 22, 2011

    Hello Sean, I am indeed very grateful to you for putting up this info in your blog.

    I have been facing this error since 2 days. But to my surprise, I have put the key hash in my app as well as tried the “UGLY” method. UGLy approach seems to work fine, everytime i uninstall the updates for fb and run my code, and it just works perfect. But when I delete the app and say reinstall the fb from the market, it will obviously generate the new version. When I click on “Login to fb” it says authorize and comes back to the home screen. leaving a message in the logcat saying “invalid key error”. What else do I need to check buddy?

  • Andre Leitao on August 22, 2011

    My development environment is a Windows Vista and I read in stackoverflow thats it may causing the still existing “Invalid key error”.

    What you have to say about this? I really need to install cygwin to be able to correctly generate the key hash (I am already able to generate it, including with the password prompt, but the error remains)

  • Kartik on August 24, 2011

    Hi, Im on a Mac and whenever i run the following command

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

    I get an error sayin “Illegal option: -exportcert”

    Please help

  • Anh Le Tuan on September 5, 2011

    Thank so much. I should have found this blog a week ago.

  • Marceliz on September 7, 2011

    Thnks it was really helpful!!!!

  • Shubham on September 8, 2011

    Hello frind,

    i am using same what u explain here ..it’s totally good one..but at end it asking for keystore file password..whatever i give it responding me same key .. ga0RGNYHvNM5d0SLGQfpQWAPGJ8= ..can u suggest me what i m doing wrong/missing.

    pls mail me at shubhampatni86@gmail.com if possible
    thanks again

  • andorraclaim on November 29, 2011

    Fantastic article, you saved me a headache and I owe you a beer. Salud!

  • Victor Pease on December 15, 2011

    Hi. nice post.

    But i am facing a problem that i think its related to this. My application is working fine as long as i login with the facebook user who owns the app. If i try to login with a different FB user, the SSO form pop up but shows and error “An error ocurred. Please try again later”.

    If i add the user to a role in my FB app, this error disappear but i want to be able to provide access to any FB user. What am i missing here?

  • Enabling PhoneGap apps to access Facebook SSO – BigGek on December 23, 2011

    [...] to Sean Lynch for posting about this and saving me from throwing my computer through a window when I got this [...]

  • rooban abraham on January 3, 2012

    I have followed your method but still not working, it working in s2 but this was not working in Sony Ericsson mobiles. what can do for solving this? pls ,

    When i login to Facebook for authentication this does not give any response in Sony Ericsson mobiles. simply closed the dialog with out any response.

  • Sean on January 4, 2012

    Unfortunately, I’m not sure why their SDK would not work on Sony Ericsson devices. Can you confirm it works on other phones? Do you actually get logging output from your Sony Ericsson devices?

    I would contact Facebook. If you can get the same code working on non-SE devices, they might have a bug.

  • rooban abraham on January 5, 2012

    Yes all other device like S2, even in emulator which was working but in SE mobile alone i am not getting any response when i attempting authenticate user. this simply opening the loading dialog and after some time it disappear without any log.

  • Hakem Zaied on January 6, 2012

    Thanks very much your are a lifesaver

  • Dmitriy Krivoshey on January 23, 2012

    Extremly usefull info! Thanks a lot!

  • AbdulFattah Popoola on February 12, 2012

    Bravo!!

    Thanks a lot!! This problem frustrated me really but your article was spot on!

    Thanks once again :).

  • Nikhil.K on February 17, 2012

    But not able to logout from our applicaton. i followed above steps..Login successfully.

    please show me a sample for logout or please explain logout and something like delete the permissions

    Thanks in advance

  • Dale Hamill on March 7, 2012

    Hey Sean!

    I stumbled upon your blog while dealing with this issue, thanks for the info, great summary.

    Question for you though:

    What do you do with non-SSO users? What I am seeing is that non-SSO users et a new token via dialog sign in, which is 24 hours expiry. The docs suggest you can extend this to 60, but it’s not clear to me how. Maybe I’m missing something obvious, maybe I’m just looking for something not well documented since its the unexpected case (who doesn’t have facebook app anyways, right?).

    Do you have details on this half of the workflow?
    What cOnfuses me is that extending a long term token can only happen every 24 hours, and by then a non-SSO token has expired. It is terrible user experience to ask for a sign in every day.

    Thoughts?

    See you around, “co-op”.
    Dale.

  • Sean on March 12, 2012

    Huh, I hadn’t even considered that most apps would have a mix of SSO and non-SSO users given that the Facebook app installation wouldn’t be universal. D’uh.

    Can you point me at the docs where you saw 60 hour limit option? At the time, I was pretty sure the option was either 24 hours or asking for a non-expiring token. Then again, I wrote this almost 9 months ago so I would be shocked if a few details hadn’t changed in the meantime.

  • gaurav jain on March 22, 2012

    Thanks for this great blog. but can you plz tell me how can i implement it . my app. failed to login if the official facebook is installed on device . i fetch the hash key and past it to Facebook but in spite of that it is generating Invalid key error. plz help me. thanks in advance.

  • Keith Johnston on May 1, 2012

    If you are getting the invalid key error, and your key is “ga0RGNYHvNM5d0SLGQfpQWAPGJ8=”, then what are you are actually seeing is the Base64 encoded error message form the keytool command. You are probably entering the wrong keystore password. The debug keystore password is “android”.

  • Login Failed: invalid_key: Android Key mismatch on June 7, 2012

    [...] have gone through link: http://sean.lyn.ch/2011/07/android-the-facebook-sdk-sso-and-you/ and many more, and found out that when using android-facebook sdk on a device (it works fine on [...]

  • Tom on June 22, 2012

    I am also fetching the has key and have passed to Facebook with no help. I am using the debug keystore password “android” what else could it be?

  • Tony on July 15, 2012

    For me the API gives no errors, isSessionValid() returns true, but any attempt to do anything gives:

    {“error”:{“message”:”An active access token must be used to query information about the current user.”,”type”:”OAuthException”,”code”:2500}}

    So presumably I have to ‘activate’ the login somehow, but there’s nothing like an ‘activate’ function or anything obvious.

  • syjsh on July 19, 2012

    such a great help! Thank you!

  • bb on September 17, 2012

    good explanation. saved me a lot of time. thanks!

  • Amal on June 27, 2013

    The older native facebook app doesnot suppport sso. So even if you do all the steps correctly, it wont work.. Please add this too.

  • Lil Wyte Oxy cotton on October 26, 2013

    So such treatment dos can be found, even though it could
    be hard to find in the area. Prescription substance abuse and also addiction is seen as a thee shortcoming from the individual to prevent making use of these drugs.
    The particular OxyContin outbreak hass made lifestyle vewry difficult for a lot of homes.

  • Alpha on November 7, 2013

    Hi Sean, Great Blog, I wrote to you because I am having problems logging into facebook, I apparently generate key correctly and follow the steps to register on Facebook. In the emulator I get the login window, but on a device screen turns black and closes without showing errors. If you can help I would be very grateful to you

  • Vindhya Pratap on December 16, 2013

    Thanks Sean it works for me the Keystore is app Keystore you can get this keystore by runnig this command in your
    acticty…

    try {
    PackageInfo info = getPackageManager().getPackageInfo(
    “com.facebook.samples.hellofacebook”,
    PackageManager.GET_SIGNATURES);
    for (Signature signature : info.signatures) {
    MessageDigest md = MessageDigest.getInstance(“SHA”);
    md.update(signature.toByteArray());
    Log.d(“KeyHash:”, Base64.encodeToString(md.digest(), Base64.DEFAULT));
    }
    } catch (NameNotFoundException e) {

    } catch (NoSuchAlgorithmException e) {

    }

    See logcat copy the keystore remove equal sign i it have then paste it to developer.

  • Vindhya Pratap on December 16, 2013

    here in above comment keystore is keyHash

  • Foot Pain Prevention on July 22, 2014

    fantastic points altogether, you just won a
    new reader. What might you suggest in regards
    to your post that you made some days ago? Any sure?

Leave a comment