OAuth on the iPhone
Programming, Security, Software, Web Development September 8th, 2008 - 15,561 viewsAnyone who’s interested in security on the web has probably already heard of OAuth. I’ll skip the details of how OAuth works, since that information is available elsewhere, but here’s the short version (OAuth veterans may choose to skip the next three paragraphs):
Before we get started, let me define a bit of terminology from the OAuth Spec:
- Service Provider: A web application that allows access via OAuth.
- User: An individual who has an account with the Service Provider.
- Consumer: A website or application that uses OAuth to access the Service Provider on behalf of the User.
- Protected Resource(s): Data controlled by the Service Provider, which the Consumer can access through authentication.
API authentication is tricky. The naive approach is to have third party (Consumer) applications ask the User for their credentials, and pass them along to the Service Provider for authentication. This is bad. Even if the User trusts the Consumer, you’re telling people that it’s Ok to give out their secret credentials. Think how much more successful phishing would be if users were legitimately asked on a regular basis to provide account information via email. There are more subtle problems, too: it’s impossible to give Consumers different access levels, impossible to revoke access for a particular Consumer, and there’s no central place that tells a User which Consumers have access to their account.
OAuth solves all these problems by having the Consumer authenticate with the Service Provider, and allowing the User to grant Consumers access to their Protected Resources. Consumers never touch User credentials. In fact, they don’t even need to know who the user is. The level of access the Consumer has is entirely up to the Service Provider and the User. Access control can be managed at the Service Provider, where a central list of linked Consumers can be displayed. Since each Consumer is given a unique access token, different permissions can be granted to each.
OAuth on the iPhone
For the past couple months, I’ve been working on and off building a native iPhone application for Pownce. The Pownce API uses OAuth for authentication, which I wanted to use on the iPhone. But for the OAuth flow to work, the User must be directed to an authorization page on the Service Provider’s web site. This poses a problem for native iPhone applications — the iPhone can only run one application at a time, so opening the authorization URL in Safari terminates the Consumer application.
But there’s a solution. The iPhone allows native applications to register with the OS to handle certain URL schemes. By registering pownce:// and instructing the Service Provider to redirect the User to pownce://access_token after authorization, the native Pownce application is automatically relaunched. The flow looks something like this:
A couple of days before the app store opened, I demoed the soon-to-be-released Pownce iPhone app to a group of folks at the OAuth Summit. Following the summit, Chris Messina, Simon Willison, and others pointed to Pownce as an example of “the right way” to use OAuth on the iPhone. Everything seemed great… until the app store launched.
The Problem…
Turns out Chris Messina and Simon Willison aren’t your average User. They understood why Safari was being launched. The average User didn’t. We started getting reviews in the app store complaining about the auth flow, and early statistics show that nearly 40% of users who downloaded the Pownce application never linked it with a Pownce account (there are other reasons a user might never link their account, but I’m sure the auth flow contributed — if anyone has stats for another app as a point of comparison, I’d love to see them). Needless to say, this situation is not good.
The Solution?
The naive solution is simple. The iPhone SDK provides a UIWebView control that lets applications integrate a web page with their UI. Instead of launching Safari, a Consumer could use a UIWebView to integrate the authorization page with the rest of their application. But this solution is not ideal because the User has no way of knowing whether they’re actually looking at the Service Provider’s site, or a fake. (In reality, as Eston Bond pointed out to me, the entire OAuth flow from the Pownce app to Safari and back could be faked fairly easily too, but I’ll conveniently ignore that for now).
The solution here, I think, is to have some mechanism (other than the URL and browser chrome) that gives the User a clear indication as to whether or not they’re on the Service Provider’s site. Something like Bank of America’s SiteKey would work perfectly. The Service Provider could split the authorization process into two steps. The first step would simply ask for a username and display a CAPTCHA. The second step would display an image that the User has previously selected, and prompt for a password. If the User doesn’t recognize the image in the second step, they should be suspicious.
The obvious downside is that the Service Provider needs to ask every User to choose a security image prior to the authorization process. SiteKey is also susceptible to man-in-the-middle attacks, but that might be solvable using a CAPTCHA in the first step of the authorization process (I haven’t thought too hard about it). In any case, I’d love to hear what the community has to say on this particular topic. There’s an obvious balancing act going on here between usability and security. What’s the optimal mix?



September 8th, 2008 at 4:23 pm
interesting post, good luck finding the best way to achieve the balance you’re looking for. Additionally, is this a sign of whats to come or should I expect another entry in 6-8 months :)
September 8th, 2008 at 5:11 pm
The trouble with OAuth currently is that the support in non-webbrowser apps is tricky at best, for the reasons above. I’ve gone through some of the same thoughts above… a ‘trusted’ framework/sdk level component that can do the whole process is one idea, but falls to the same ’spoofing’ problem as a web page.
The SiteKey is interesting, but makes it hard for folks who are signing up through the device (which is a whole different set of problems as far as trust goes anyway).
We’re currently ‘cheating’ in the Photobucket app - we have a ‘private’ method for trusted partners to do direct authentication without a webpage, which returns oauth access tokens. We then only cache the access tokens, so at least we’re not keeping the username/password around, but its not ideal either.
September 8th, 2008 at 6:28 pm
So, my base viewpoints are that :
1. Performing the auth inside a third party app, regardless of the underlying technology, is not OK. It trains users to enter their passwords into an untrusted context, and thus is no better than the existing password anti-pattern that OAuth tries to get us away from. Embedded controls have no means of URL/HTTPS verification, and so are unsuitable for authentication.
2. I actually think that the App -> Safari -> App pattern is extremely neat and can work really well, especially compared to traditional mobile and desktop auth, which forces you to type numbers between apps, or manually relaunch.
So, my feeling on the Pownce app:
I’m inclined not to read too much into the 40% failure figure. The app got featured, I believe, and in the App store opening frenzy many non-Pownce users will download it. To someone who also needs to register for the service, your authentication flow is more complex and I think not as clear as it could be.
I think the pre-auth prompt, within the app, could be clearer. Explicitly stating that the user needs a Pownce account to use the app is important, especially when a large potential audience are new to Pownce. Perhaps offering a separate ‘Register’ and ‘Sign In’ button within the app, linking directly to a different entry point in the authentication flow, would remove much of the confusion.
— In the login prompt itself, the ‘Signup’ link is somewhat unobvious. It kinda looks like a heading and not a link or button. As such, I wonder if much of that 40% got to the log-in page and gave up because they didn’t acknowledge the ability to register, not because they have been moved to their web browser.
I think that a fuller welcome screen with better explanation of what the user needs to do to auth the app would be more effective; rather than an ‘OK prompt’ style welcome (which users are known to habitually click through without reading).
Now, none of this is to say that OAuth is the be all and end all of auth. There are, I’m sure, better ways to do this and we shouldn’t hold back trying to suss them out. However, OAuth operating the way it does, I think it’s vital that the application context and the browser context remain absolutely separate.
September 8th, 2008 at 6:35 pm
And the important paragraph I left out there, was to say that when you *are* already a Pownce user and only have to log-in, I think the flow works really really well. I was genuinely delighted the first time I used it and it relaunched the app.
A little more instruction to users and I think users will be OK with it.
September 8th, 2008 at 7:01 pm
I installed the pownce application yesterday and I thought the authentication component was flawless. I wasn’t confused at all. Then again, I was on WiFi and it happened very quickly, maybe I would have had more questions if it was happening slowly.
September 8th, 2008 at 7:12 pm
Ben, I thought the auth flow worked really well too. I think everyone who understands it/understands OAuth thinks it works really well. It’s definitely _way_ better than making people manually move back and forth between the app and the browser. But lots of people who aren’t that tech savvy are somewhat frustrated by it. It’s very hard for me to judge how big of an impediment this is. Since Pownce is a small company, our “usability testing” consists of asking friends. Most of my friends are tech savvy. Blah.
I did think Eston made a good point the other day when I was discussing this with him. In reality, on the iPhone, the App -> Safari -> App flow is only marginally more secure than an embedded UIWebView in preventing phishing. Re-creating Safari is trivial using a UIWebView and a couple of other UI elements. The URL could be faked in your “custom” Safari lookalike. The animations between the app and Safari could be faked using Core Animation. I’m pretty sure the bookmark bar could be reproduced, since the bookmarks are available via one of the SDK APIs. In short, a user would have to look _really_ hard to tell if you’re using the _real_ Safari. Sure, building a fake Safari and whatnot is more work, but it’s possible. So I’m struggling to find a reason why using an embedded UIWebView is any worse than what Pownce is doing now. And I think using a Sitekey like solution along with an embedded UIWebView would be much _more_ secure.
Anyways… lots of incomplete thoughts and whatnot. I definitely want to get a conversation going on this though, because I’m still far from convinced that we’ve got the ideal solution here.
September 8th, 2008 at 7:14 pm
On the desktop Flickr Uploadr we stuck hard to the browser-based authentication model. It’s important to dogfood the entire API. It’s more important to remember that anything not running on Flickr’s webservers has to be treated as untrusted or they risk taking input from whatever owned Windows box happens to have Flickr Uploadr installed. (I assume that problem is still relatively rare in iPhone-land.) After a trip to Flickr, folks were invited to switch back to Flickr Uploadr and click the big “Ready” button. A custom URL scheme akin to pownce:// would have taken more clever than I had at the time but is really a nice way to dictate the flow.
I’d love to see Apple take a stance in favor of OAuth via Safari and custom URL schemes as the Right Way to create iPhone (or OS X) clients for web apps.