good-bad-uglyIn the previous post of the series, we explored the basics of OAuth authorization. In this post, we will propose three possible alternatives for implementing authentication using a REST API backend and a mobile frontend. Let’s remember our scenario:

You are developing a RESTful API as the backend for a mobile App frontend. The App will communicate with your REST API to perform CRUD operations on the data. You will allow the user to authenticate against the REST server by a common username/password scheme and you will also allow social login, by means of the usual “login with Facebook” or “login with Twitter” buttons on your App. You want to integrate the social authentication seamlessly into your App User Experience. Once logged in, the App will communicate with the REST API in behalf of the user to do the CRUD operations.

When faced with this scenario in the past, I have developed several alternatives that I call the good, the bad and the ugly. Let’s present them in order of desirability.

The Bad

This method consists in generating the user’s credential from certain parts of the user’s social data and the credentials of your app in that social platform. It’s an adaptation of the Client Credentials flow of OAuth 2, and assumes you have created an App in the social network’s developers site, and you have a client ID and client secret. The process would follow these steps:

  1. You user clicks on the social login icon (Facebook, Twitter, Google+…) and gets asked for authorization to access his basic info.
  2. The user accepts and your App gets some of his info, including his user ID in the social platform, his name, and optionally more data (like the user’s avatar image, email, location…).
  3. The app generates a user ID based on the user’s social network ID and perhaps some other data, and it generates a user’s secret with a combination of the App credentials (client ID and client secret) and the user data, by means of a cryptographically generated string or a hash. This hash should be generated in a way that it would always return the same string for the same user (in a given social network), and it would be impossible to extract the client credentials from the hashed string or infer other user’s secrets by knowing their user’s data alone.

This user’s ID and user’s secret would then be used as the authentication credentials for your REST API. In order for this method to be secure and effective, it is important that the client credentials and exact hashing mechanism are not made public. In order to avoid having the client credentials stored in your App (where they could be retrieved by means of reverse engineering), they can be stored securely in the REST server, and so the REST server will be in charge of calculating the hashed client’s secret and pass it to the App. HTTPs is, obviously, mandatory in this kind of authentication.

Advantages

  • No password are needed, and the user never needs to remember one.
  • Relatively easy to implement.
  • Easy for the user, that just needs to click a social login button.
  • The user’s secret can be stored in the App to allow for quick login, or easily regenerated by just asking for the user’s social data again.

Disadvantages

  • If the client credentials are stored in the App, they could be retrieved by reverse engineering and used to impersonate any user in your REST API. If not, an additional mechanism must be set to assure that the user requesting the user’s secret is actually who he say he is.
  • There is no real authentication. The user is just asked to authorize from his social network’s profile, but anyone with access to the user’s device could impersonate him.

This mechanism is sadly misused by a lot of developers when first faced with the complexities of OAuth. Without a deep understanding of security and authentication, and additional measures, it is easy to implement a custom variant of this scheme that would result in a weak, easy to break authentication system.

The Ugly

This is an hybrid mechanism that uses OAuth as a way of retrieving the user’s data from the social network, and a password for real authentication. This method is marginally better than a pure username/password schema from a user experience point of view, because the user’s identity is automatically selected/retrieved from his social data, but it includes a password that assures a real authentication process, where the user must explicitly demonstrate his identity. HTTPs is mandatory for avoiding the user’s password being transmitted in clear. The process is the following:

  1. Your user clicks on the social login icon (Facebook, Twitter, Google+…), and gets asked for authorization to access his basic info.
  2. The user accepts and his info is retrieved from the social network. The user is presented with a password field.
  3. The user fills the password. Then your App will use some of his data (presumably the user name from the social network or email if available) and the provided password as credentials for your REST Server.
  4. Each restart of the App will retrieve the user’s identity from the social network, and the user would just need to enter his password.

From the point of view of the UX/UI, this method has the advantage that, once the user authorizes the app, he can be presented a personalized view with his avatar image, name and possibly other data, and the user just has to fill a password.

Advantages

  • This method implies real authentication. The user needs to explicitly enter the password in each login, thus assuring his identity.
  • Easy to implement, both in the frontend and in the backend.
  • Easy to integrate in (expand from) a username/password schema.

Disadvantages

  • The user needs to remember another password, thus defeating somehow the social login initial purpose.

This strategy is good if you don’t mind asking you users for passwords, and allows you to avoid prompting the user for all his information. Nevertheless, it is still closer to the username/password user experience than to merely pushing a “Login with Facebook/Twitter” button.

The Good

This authentication mechanism implies forgetting everything about usernames and passwords and embracing another way of thinking about the authentication. The user will not be requested to give a password, neither a secret would be generated to be used as credentials. Instead, we will use a process that some people call “Reverse OAuth authentication”. It consists in obtaining a valid access token from the user’s social network, and then sending it along with the user’s identifier to the REST server. The communication goes through a secure HTTPs channel. The REST server will contact the OAuth authorization server and verify the user’s credentials using the access token. The short-lived nature of this token will assure that the identity of the user is not compromised in the long-term. The main social networks have the following verification endpoints:

  • Twitter: https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials
  • Facebook: https://graph.facebook.com/me

Once the REST API successfully verifies the identity of the user, it responds with the pertinent user object and the API Key for using the REST API. No credentials are needed, and there’s no need for the user to remember a username or password. The API Key can be used until it expires (if applicable) or the user explicitly logs out. When the user needs to login again, it will repeat this process, with another generated short-lived token.

Advantages

  • No need for password or user credentials.
  • Secure for your App. You don’t need to store passwords or access tokens permanently.
  • Easy for the user to understand and use in an App.

Disadvantages

  • There is no real authentication. The user is just asked to authorize from his social network’s profile, but anyone with access to the user’s device could impersonate him.
  • Very difficult to implement and not very intuitive to understand for the developer.

This last mechanism is, in my opinion, the only real way to implement authentication using OAuth authorization, the only one that would not require a password from the user and still guarantee some kind of security and trust for both the user and the REST server. In the following post of this series, I will discuss this last mechanism in depth, explaining it and including complete sources for implementing it on your own REST API server. Have an alternative method? Did I miss something? please let me know in the comments.