OAuth2

OAuth2

OAuth 2 is an authorization framework, for implementing a mechanism to allow you to grant apps and websites permission to access your data on app/website X. For instance, an app might legitimately want to access Facebook friends, Flickr albums, etc., and OAuth2 provides a safe way to let it do exactly that in a safe manner.

It can also be used for authentication, providing a way for an app to make sure you’re who you claim to be, using the same concept as above to pull your personal info from third-party websites instead of making you enter it all over again.

There are specific flows for web, desktop, mobile apps, and more (TVs, game consoles, etc), and different situations and needs.

If you have 59 minutes and can grasp new concepts quickly, watch this video. It’s IMHO the best for OAuth2:

Why OAuth? (ELI5)

Pretending you’re a photographer, you might have spent countless hours to upload your work to Flickr.

Now you want to use a random third-party app to create galleries for your website, another app to catalog them, and yet another custom app you had someone program for you to keep track of what prints you sold for each photograph.

Obviously, uploading all your pictures 3 times while you’ve already done that doesn’t make any sense.

While 5-10 years ago services tried to lock you in into their technology and wouldn’t allow this, most services now expose a way to let other apps talk to it and—in our case—get the photos automatically.

Now, to gain access to Flickr, apps could ask for your username and password, and log in like they’re you to get the data they need. However, this would cause a few problems:

  • your credentials are stored in many places, so the chances of a getting hacked are higher
  • if you change the password, you’d have to remember all the apps you granted access to and change it there, too.
  • because of how passwords work, the apps would be given full access to your account (let’s say including your billing info), while they should only be able to have read access to your photos
  • there is no easy way to revoke access to a particular app, without changing the password everywhere else

OAuth2 solves all of the above challenges:

  • it allows connection ing to apps/websites without sharing your credentials
  • it allows to limit what data you share
  • it allows you to revoke the permission you granted and block access again

Plus:

  • it helps minimize number of password users have to remember
  • good for those of us that like to use “yomama” as our main password for everything—since you’re not sharing it, even if it gets compromized you only have to change it in 1-2 places
  • for developers, users can get on board faster and might be more willing to do so

There’s also a pretty good video that gives a nice overview of OAuth2 concepts:

Before you get started

Terminology

Before doing anything else, there are a few terms related to OAuth that you might want to know. Here’s a list:

OAuth roles

There are four players in an OAuth authentication flow:

1. resource owner—the user who owns the data/authorizes access to the data. A human being would call this user.
2. client—the app that is requesting the data. A human being would call this app or website.
3. resource server—he service/server that holds the data. A human being would call this API server.
4. authorization server—the service/server that grants access to the data. A human being would ignore this term because it’s usually a component on the resource server.

So, resource owner = user, client = app, resource server = API server (or simply API). Authorization server, who cares.

Authorization vs. authentication

It’s easy to get confused.

OAuth can be used to control both access to data (more common) and identity. That’s authorization and authentication. Two different things:

  • authentication: verifying you are who you claim to be
  • authorization: making sure you only see what you’re supposed to see

Note on encryption

Besides terminology, this is pretty important to know.

With OAuth 2, you can safely get access to user data, but provided everything is encrypted with TLS/SSL (so, both the client and the server).

Contrary to OAuth 1, OAuth 2 doesn’t offer any security layer like cryptography and signatures, and leaves it up to the user to always use HTTPS.

If OAuth is used without TSL and valid certificates it’s pretty much useless.

How OAuth2 works (ELI5)

OAuth is very much about exchanging messages between the client and the API server.

Usually, the client will let the API know it would like to access data on behalf of a certain user, identifying itself and providing some form of authentication, by making a HTTP call, for instance:

https://api.provider.com/token?client_id=123&scope=read_this,read_that&redirect_uri=myapp.com/oauth/

The API will then validate the information provided, and redirect to a URI belonging to the client app, with either the access_token or a way for the client to get the access_token, for instance:

https://myapp.com/oauth/?access_token=123x0etc12etc

Standard implementation (app developers)

Usually, if you’re developing a client app you’ll have to register it with the resource provider (let’s say Flickr).

You will:

  1. perhaps login into Flickr or give your email
  2. give Flickr a redirect URI, which is where Flickr will redirect to

Flickr will:

  1. give you a client_id
  2. give you a client_secret

In its simplest form, there’s nothing more to it that I can think of.

Access tokens

OAuth revolves around access tokens.

Access tokens represent the user’s permission for the client (aka “app”) to access their data.

I actually remember Italy’s double-grove phone tokens. You had to go to a store, exchange money for these tokens and then go to the phone booth and you could make a phone call. Weird. Well, access tokens are the same. The end-goal of every OAuth2 flow is to get an access token, but instead of making a phone call you get access to a user’s data (much better).

Access tokens are simply long, hard-to-guess strings (like njd9wng4d0ycwnn3g4d1jm30yig4d27iom5lg4d3) that grant the client (aka “app”) permission to read the user’s (aka “resource owner”) data.

The client sends an access token to the the resource server (aka “API server”), which validates it and returns the data requested. In its simplest form, pretending that https://example.com/users/1/friends can return a list of friends if you have access to them, https://example.com/users/1/friends?access_token=njd9wng4d0ycwnn3g4d1jm30yig4d27iom5lg4d3 would give you a JSON (or whatever) containing a list of friends.

Expiration

Access tokens expire, usually within 1 hours from being issued. This is a security measure, and it’s good: if someone gets hold of your access_token, it won’t be within 1 hour.

Scope

Like mentioned, access to data can also be limited to the scope of the authorization granted.

Scope can be something simple like read/write or more complicated and app-specific, like can_read_emails, can_make_phone_calls (or whatever you want to limit).

When the client asks for an access token, it can specify what level of access is required. For instance, if the API server is Flickr, a client app might reasonably need to access your basic info and photos, but not your billing info. So, we might specify our scope like this: “scope=basic_info, photos”. Flickr’s own iOS app might want to access billing info as well, and then the request would include: scope=basic_info, photos,billing_info”.

Like mentioned, scopes are totally up to the API developer. They are not standardized in any way (that I know of).

Grants

With OAuth2 users grant client apps permission to access data—the permission being represented by an access token. The process—or workflow—by which the client app gets an access token is called grant.

The end goal of grants is for the client app to get an access token, and therefore permission to access data.

There are different workflows for specific situations. These workflows are called grant types.

Grant types

Grant types are basically standardized ways to give a client an access token. They translate into a flow that you must follow when implementing that grant type, and the best grant type to use depends on your situation.

Grant types are listed here: http://bshaffer.github.io/oauth2-server-php-docs/overview/grant-types/, and there’s an awesome article on grant types that you should read: http://alexbilbie.com/2013/02/a-guide-to-oauth-2-grants.

Now, which grant types are available? It should be noted that OAuth2—being a framework that doesn’t impose a lot of constraints—allows to create grant types at will, so many client libs come with helpers to do that.

Having said that, at the time of writing only 4 have been standardized (plus 1 to get a refresh token but it’s not really a grant I’d say).

I’m only interested in 2 of them—the ones used for web apps—so I have no idea about the other 2 just yet (see http://alexbilbie.com/2013/02/a-guide-to-oauth-2-grants if you’re interested).

Here they are.

Implicit grant

This is the stupidest of all grant types. It allows the client to call the API server, include its ID, scope and little more in the request, and get an access token in exchange. Then, the client would store this access token for following calls to the API.

This is pretty basic, and it’s usually used for js-based apps, where everything is on the client side.

In client-side applications, from the app you will get a popup that if everything is ok will add a hash fragment to the URL in your main app window which contains the access token.

The provider will open a popup with info as GET parameters. These could be your client ID, and can use a redirect_uri parameter that you specified, which will be the Url that the thing will redirect to if successful. Example:

https://api.provider.com/auth?client_id=123456&scope=appservice1,appservice2&redirect_uri=https://app.com/callback.html&response_type=token

The API will return an access_token. This is all you need to access the API on behalf of the user. OAuth 2 rarely requires cryptographic signatures. The token will be passed in the URL.

OAuth2 assumes you’re using TLS. If you’re not, it’s pretty bad.

API might return the expires_in (3600 seconds, or 1h).

Example:

https://app.com/callback.html#access_token=longstringofrandomcharacters&token_type=Bearer&expires_in=3600

To get the access token back from the pop up window to the app, you should use HTML5 postMessage, or you can use window.opener if you need to support <= IE7 very old browsers (<IE8).

To get a fresh access token when this one expired, you go through the same process (although the user won’t need to confirm since he’s already authorized, there are also ways to do it w/out showing the pop up window).

Authorization code grant

This is the grant people think of when talking about OAuth2.

It’s often used to get offline access to the data, so talking to the API even when the user isn’t using your app, but can be used to add a level of security over the implicit authorization grant even if you don’t need offline access.

This workflow requires you to pass your client secret to the API server. As the client secret MUST BE KEPT SECRET, this grant type CANNOT be used for client-based app, as anyone could open your JS source code and see your client secret.

The API endpoint might look similar to the implicit authorization grant, with a few extra parameters:

https://api.provider.com/auth?client_id=123456&scope=appservice1,appservice2&redirect_uri=http://app.com/callback.html&response_type=code&access_type=offline

The big different is that instead of appending the access token to your redirect URI, the API server will append an authorization code.

An authorization code is an intermediary code used to get the access token. The added security rests in the fact that in order to exchange your authorization code for an access code, you need to include your client secret, and since it’s supposed to be secret, the app server knows it’s you.

For instance, the client library might simply make a HTTP POST call, like:

POST https://api.provider.com/auth/token?client_id=123456&grant_type=auth_code&code=rurufhfhfueiwosm&client_secret=fjfjdisjsk

The API server should return JSON looking similar to this:

{
"access_token": "...",
"refresh_token": "...",
"expires_in": 3600,
"token_type": "Bearer"
}

To get a refresh token:

POST https://api.provider.com/auth/token?client_id=123456&client_secret=fjfjdisjsk&grant_type=refresh_token&refresh_token=rurufhfhfueiwosm

Refresh tokens NEVER EXPIRE, unless the user revokes access. In that case, you’ll have to start over.

Refresh tokens are usually stored on your user database. Refresh tokens in themselves aren’t that valuable unless combined with the client secret, so you can safely store them on the database, but make sure you keep the client secret secure in a key store or something like that and limit access!

Conclusion

I might be dumb, but it took me a while to wrap my head around these concepts, but after a while I think I got it (hopefully).

There are a few libraries that are great for working with OAuth2: hello.js for client-side applications, and HybridAuth for server-side apps. Both build a lot of functionality on top of social login, and create an unified API to pull data from the most popular social networks.

If there are any fuck-ups in this article, please let me know in the comments. Thanks!

2 thoughts on “OAuth2

  1. This might be one of the best explaination on Oauth 2 I’ve ever read. Thank you so much. I was struggling to understand the whole picture. This makes it so clear.

Leave a Reply

Your email address will not be published. Required fields are marked *