Skip to end of metadata
Go to start of metadata
Last week, I was working on improving the initial implementation for federatedaccounts. Some of you might have preferred that I spend my time implementing more OAuth providers or a generic OpenId provider but since I have the itch to scratch, I instead decided on implementing a configurable window mode for the existing Facebook Oauth integration, in order to improve its usability and customizability. Now, the window mode refers to how the (the response to the) callback URL is presented to the user. Three basic choices is either self, blank or inline. See our federatedaccounts demo if you don't know what these mean. Self and blank should be straight-forwarded, but by attempting to implement inline (just to see how far I'd get with it...), i.e. an (i)frame-based window mode, I of course landed right in the middle of the whole clickjacking or UI redressing attack controversy. The core problem is that browsers and the html standards don't provide any good, end-user friendly means for verifying the origins of an iframe content. Therefore, the security conscious Oauth folks (see e.g. http://simonwillison.net/2009/Jul/16/responsibility/) say (rightly so) that you should never ever allow processing an Oauth request in an iframe since the URL is not shown to the user and it's simple to fake the dialog UI. In contrast, the user experience experts argue that popping out windows or suddenly transferring the user to a different site makes the user feel more confused and insecure (see e.g. http://drstarcat.com/archives/133), and that the frame busters are meaningless as the majority of users won't pay any attention to the URL anyway. I happen to agree with both sides. Relying on the user to validate the URL, especially without any additional visual clues (compare to how modern browsers display https URLs with valid SSL certifates) is way too weak as a real security measure, but if that's all you got, it's certainly better than nothing. On the usability side, launching a new browser window, or doing a full page refresh, is somewhat confusing and way slower than loading content into a pre-existing iframe. What's lost in all of this, is that Oauthis supposed to be about authorizing users, not authenticating them.

Notice how above I first blamed the browsers for not solving the problem, but then ended up sharing the blame with OAuth. That's because a) the UI redressing problem is not specific to OAuth and b) UI redressing is a super-tricky problem to solve. Simply displaying the URL of an iframe (even if browser assisted) is not nearly enough because that too can be easily redressed (see more at http://www.webmonkey.com/2008/10/a_look_at_the__clickjacking__web_attack_and_why_you_should_worry/). Browser developers do are trying to do something about the problem but they just don't agree on exactly what is the right measure (see e.g http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-September/016286.html).

So, while waiting for a standards-based solution to the problem is there anything that can be done to improve the user experience of (FB's) OAuth dialog flow? The inline window mode works great if a) you are already authenticated with Facebook (i.e. you have a valid Facebook cookie) and b) you've previously authorized the subject application. However, in all other cases, the inline mode isn't too useful since it's not that simple to find out if the current user is logged onto Facebook or not. You can find the status with FB.getLoginStatus() but you have to include FB's Javascript SDK to the page. The other issue is the frame busting code. Facebook doesn't allow any of its pages to be displayed in an iframe. Instead they simply display a link to "Visit Facebook" when shown in an IFrame. There's no technical or security-related reason why Facebook couldn't allow showing the Oauth authorization window in an iframe when the user is pre-authenticated via cookies. In fact, Facebook already (almost) had this working with Facebook Connect, only it had one crucial flaw: it was asking for user's Facebook username and password in the same dialog.

To improve usability without asking for user's credentials in the same Oauth authorization dialog, Facebook could potentially allow passing a one-time valid user authentication token with the Oauth request, but in some ways that would only shift the responsibility somewhere else. There's an open standard for that as well, called OpenID, and you can by all means use OpenID together with OAuth as demonstrated by Google . Unfortunately though, the window redressing attack is just as big of a problem for OpenID as it is for OAuth. Since OpenID was originally meant for authentication only (though the attribute extensions make it partly an authorization technique) you cannot shift the responsibility any further. I'm not advocating the use of hybrid OpenID+Oauth model either - it may just increase complexity without improving user experience. However, we may be throwing the baby out with the bath water by never allowing Oauth dialogs to be shown in iframes. Certainly the authorization server has to be able to authenticate the end user one way or another, but handling an Oauth callback in an iframe is perfectly secure if you never ask the user's password in the same dialog. Anyhow, with the current standards there's no way out without major security implications, so browsers and ultimately, newer standards need to provide a better, more secure solution.

  • No labels