Let’s face this: Users don’t like passwords. At all. They don’t want to remember a user and password for every site they have an account in: Twitter, Facebook, Tumblr, Instagram… the list goes on and on.
As an iOS developer, I am frequently required to develop an App following the classic pattern of mobile frontend for a RESTful Web Services backend. One of the common requisites for this kind of Apps is the social login, i.e: enabling the users to log in via their Facebook or Twitter accounts (nobody usually cares about that digital wasteland called Google+). The solution is simple (or at least they say so): authenticate using Twitter or Facebook OAuth tokens. I always cringe in terror when I hear these words.
First of all, OAuth is not an authentication protocol, OAuth is an authorization protocol. Authentication means identifying the user by his or her credentials, whereas authorization means granting access to certain information about the user. The fact is that most developers and platforms are using OAuth for authentication. We are using the wrong protocol. Of course, there is openID, but it is built on top of the OAuth specification, present the same problems for developers, and no-one is using it either.
Leaving that point aside, I think OAuth is a dreadful protocol, both for the developers of an App and for its users, and I am not the only one. The web is full of horror stories of developers trying to implement or interact with OAuth, and even the lead author and editor of OAuth v1 resigned and removed his name from the specification when version 2 was released. However, as OAuth has become the de-facto standard for interaction with social networks these days, I plan on releasing a series of posts on how to implement your RESTful platform with support for OAuth reverse authentication via popular social networks. But before that, let me explain you the drawbacks (in my opinion) of using this protocol for authenticating your users:
It is unnecessarily complex and difficult to understand.
OAuth is (in my opinion) a difficult protocol, unnecessarily difficult. Its flows are not intuitive at all, and it leaves many loose ends, which are precisely the aspects that are most important to developers. I have studied the OAuth specification lots of times and read many books about it, and I still don’t completely get it. And it’s not just me. I don’t know any frontend or backend developer who will admit to fully understand it.
One of the main points of confusion are the different authorization flows. Each kind of scenario (server-side web applications, web clients, native applications…) has its own authorization flow, with different types of tokens, permissions and authorization codes. First part of the upcoming series of articles about OAuth will focus on understanding OAuth authorization flows.
To make things even worse, each web service and social network out there has implemented OAuth differently, adhering to different drafts of the specification. This makes it even harder for the developer to implement a common framework for using OAuth in a mobile App or a RESTful backend.
It is ugly, and terrible for the user’s experience.
One of the main drawbacks of OAuth is that it needs the user to authorize a third party App or service to access certain information (name, email address, location…) or perform certain actions (post a tweet, read the user’s timeline…). The designated way of doing this in the OAuth specification is by redirecting the user to a webpage where he has to authenticate agains the service (if he wasn’t authenticated previously) and then authorize your app to access the information or perform the actions.
For a mobile App, this usually implies switching from your App to the device’s default browser where the user is presented with a HTTP form, although it can also be presented via an alert or dialog. However, this interaction usually means leaving the main flow of your App and, in the worst case, opening another one with a completely different design and UX. This point alone is the main deal breaker of OAuth for me. It destroys any kind of user experience that you want to build, it is ugly and un-intuitive for the user, who gets redirected back and forth from your application to the browser.
I understand that this protocol was thought with a browser client application in mind, but for today’s standards, in which the users want an integrated and seamless interaction with their devices, the OAuth has no answer for the needs of mobile Apps.
It does not solve the authentication problem
As I said before, OAuth is an authorization protocol. This means that it does not provide us with a way to authenticate the user. We can somehow infer that, if we are authorized to access certain information or perform certain actions on behalf of the user, then we are authenticated in the OAuth authorization server, but this is not enforced by the protocol, and it may not be true at all. I can get the phone of somebody else (supposing is not locked by a passcode), enter an application, click the “login with Facebook” button and when I am redirected to authorize this application, answer YES (supposing the user is already logged in on Facebook, which is actually quite common), and the application will believe that I am authenticated as the legitimate user, while I am not. If the application faced me with a username/password form, I would not be able to access the user’s account of that application.
It forces you to clutter your application code and structure.
Due to the complex nature of the protocol and for the forced interactions with the browser for the authorization, you need to clutter your code with the requests for authorization codes, redirections between the application and the browser, and access token management. The lack of a standardization when it comes to OAuth implementation also implies a lot of work in the developer’s side to make sure everything works as expected in the many services available (Twitter, Facebook, Google+, etc).
Developers end up implementing custom hacks that compromise security.
Due to the fact that OAuth is not an authentication protocol, the tokens returned by the usual authorization flows (Server-side authorization flow and Client-side web Applications flow) are short lived, which means they will expire and a new access token will need to be issued. This is the biggest problem when using OAuth for implementing authentication in your RESTful backend.
Imagine this scenario: you are developing a RESTful backend web service for a frontend, mobile (iOS/Android) App. You want to include Facebook/Twitter login in your App because you don’t want to ask the user a password and… well, because everybody else is doing it. So you decide to ask Facebook or Twitter for an access token, because this access token means the user has successfully authenticated (and authorized some permissions upon your App), so you can use the user’s id and the returned access token as credentials for your REST backend. The problem is that the access tokens expire, even the offline, longer lived refresh tokens expire, so you decide that you will store the user’s id as the “user’s login” and the access token as the “user’s password”, but what if the user deletes the application from the device? You could store them on iCloud, but Android doesn’t have iCloud, and you may find that your user has not iCloud enabled, or it could remove the iCloud account or close it and open a new one. You will be left with no way to authenticate the user again against your REST Api, because the access token will be lost forever, and your user will need to open a new account, leaving lots of clutter in your database.
When confronted with this situation, most developers will opt for a custom “hack” that will allow them to generate viable credentials from the social service id, the access token, or any information retrieved from the user’s profile. Most of the times these custom “hacks” would be poorly implemented from the point of view of security, and would be easy to crack and pwn. Remember: custom made security solutions and security through obscurity don’t work. Never.
So, what would be a suitable replacement for OAuth 2?
I’ve said before that you shouldn’t implement your own security scheme and trust security through obscurity, so what can we do? There exists openID, but I think it is pretty much dead right now, and it does not support the best known social networks (like Facebook and Twitter), so it is not a viable solution. After some research on the internet, you can discover that some of the big companies out there don’t use OAuth at all, like Amazon, who uses an hybrid signature-hashing approach, and there is even a very nice post of Riyad Kalla about how to implement a secure authentication schema for your RESTful API without OAuth. Other viable solutions would include asymmetric cryptography (actually getting closer to the OAuth v1 specification, which included signatures), or falling back to the good-old username/password scheme.
However, as I stated in the first sentence of this article, users are progressively expecting new apps to log them in using their pre-existing accounts, so I think we need to think of a brand new solution, something that would allow authentication using trusted third party services, and with enough acceptance to be adopted by the main players (Google, Facebook, Twitter, Yahoo!…). Until then, unfortunately, we must adhere to the OAuth standard to keep up with the current trends.
With all these problematics for developers in mind, I intend to release a series of articles on how to implement your own RESTful API as a backend for an iOS App frontend. The first of these articles will try to demystify OAuth and explain the main authorization flows we can use for such a challenge.