Writing
4 min
postgres · process

Using OAuth to Protect Internal REST API

March 18, 2013 · 4 min

OAuth is a very popular and widely used authentication framework. It was originally developed to allow third party apps to access resources from web sites without needing user’s credentials (id and password). And although the use case described above is raison d’etre for OAuth, it can be useful in other situations as well.

**tl;dr:**You should use OAuth 2.0 client credentials flow to secure REST APIs used in your web application.

Protecting Internal REST APIs

Let’s consider one such situation. Imagine that you built a web app which leverages RESTful APIs on the server. Naturally you want to protect your APIs against unauthorized users and other ruffians.

Since both the app and the server are under your control, it would make no sense to ask the user to grant access to the APIs. In fact, the authentication mechanism you use should be completely transparent to the user.

Now, you can obviously define your own protocol to do this. You can for example create a session id, store it in a cookie, and pass it along to the server with every request (this is essentially how Spring Security sessions work).

But, since OAuth is all the rage in web authentication circles, wouldn’t it be nice if we could use it? It would and we could.

Picking The Right Version

Fortunately, OAuth supports the use case I described above. Unfortunately, it supports that use case via two completely incompatible approaches, depending on which version you use.

In OAuth 1.0, this approach is affectionately referred to as “2-legged” authentication (meaning that the 3rd leg, i.e. user granting access to the resource is absent from the transaction). In OAuth 2.0, a new flow called “Client Credentials” was defined instead.

So, which approach is better? Is it as simple as “Just use the latest version?”. Let’s find out.

What Are These Words You Speak?

Before getting into the approaches exposed by different OAuth versions, it’s helpful to define a few terms:

  • Resource Server: server hosting the resources (your server that exposes RESTful APIs)
  • Resource Owner: user of the application (the person who logs into your app)
  • Client: the application making API requests (your app)
  • Authorization Server: the server which issues access tokens to clients after getting consent from the resource owner (note that this is a concept unique to OAuth 2.0)
  • Request Token: an object used by the client to ask for an access token
  • Access Token: an object used by the client to obtain a protected resource (in OAuth 2.0 this is also referred to as a Bearer Token)

With that out of the way, we can finally take a closer look at how each version of OAuth deals with user-less authentication.

OAuth 1.0: 2-Legged Authentication Flow

I find that understanding 2-legged authentication is easier when contrasted with normal (3-legged) flow. The concept is beautifully explained by Andrew Arnott in his post on 2-legged OAuth and I will simply parrot it here.

The normal flow looks like this:

oauth-v1_0-3-legged-flow

  1. Client asks for a Request Token from the Resource Server (Note that at this point the Request Token is unauthorized)
  2. Resource Owner authorizes the Request Token with the Resource Server
  3. Client exchanges the Request Token for an Access Token with the Resource Server
  4. Client obtains protected resources using the Access Token

2-legged flow skips authorization by the client. In other words, the Request Token returned by the resource server is pre-authorized. Otherwise, the flow is the same:

  1. Client asks for a pre-authorized Request Token from the Resource Server
  2. Client exchanges the Request Token for an Access Token with the Resource Server
  3. Client obtains protected resources using the Access Token

A few notes:

  • OAuth 1.0 requires all requests to be digitally signed. Three mechanisms are supported: PLAINTEXT, HMAC_SHA1 and RSA_SHA1. HMAC_SHA1 uses a symmetric shared secret for encoding, while RSA_SHA1 uses an asymmetric secret key pair. Though RSA_SHA1 is the most secure, it’s also the most complex to implement, so HMAC_SHA1 is typically used in practice.
  • To further secure the transmission, all requests need to supply a timestamp and a nonce value. While timestamp is obvious, nonce (i.e. “number used once”) is a random string used to uniquely identify the request. The resource server is expected to keep track of nonces in order to prevent replay attacks.
  • OAuth 1.0 is very specific about how to compute the digital signature (known as the Signature Base String).

OAuth 2.0: Client Credentials Flow

OAuth 2.0 Client Credentials Flow looks like this:

oauth-2_0-client- credentials-flow

  1. Client asks for an Access Token (i.e. Bearer Token) from the Authorization Server
  2. Client obtains protected resources using the Access Token

A few notes:

  • OAuth leaves the mechanism to authenticate the client in step 1 flexible. Some approaches include passing client_id and client_secret as POST parameters, using Authentication HTTP Header, and other mechanisms.
  • When requesting authentication, client must pass grant_type="client_credentials".
  • If successful, Authentication server should return a JSON object that contains access_token and token_type (and optionally other values).
  • The preferred mechanism to request an access token is via an Authorization HTTP Header.
  • Access token could be any value the Authorization server decides to issue. OAuth 2.0 protocol isn’t specific about this.

Comparing the Two Versions

One of the big complaints about OAuth 2.0 is that it’s not prescriptive enough, which could lead to multiple incompatible implementations. You can see this dynamic playing out here. Since it’s up to the Authentication server to decide which authentication mechanism to use, different OAuth 2.0 clients may not be compatible with that mechanism.

On the other hand, OAuth 1.0 is pretty specific about how things should work. Other than allowing for multiple mechanisms to encode digital hashes, everything else has been predefined. Therefore, a given implementation of OAuth 1.0 is very likely to work with another.

Another thing to consider is how much work it takes to actually implement the protocol. With OAuth 1.0, the work is non-trivial because a proper implementation requires supporting a complex digital encoding scheme. I should note that OAuth 1.0 implementations are available for various languages and frameworks. How well they all work is a different story.

OAuth 2.0 doesn’t require this and is therefore simpler to implement. Of course if the Authorization server decides to use a complex protocol, all bets are off.

Bottom Line

So, what does this all mean? Which version should you use to protect your precious RESTful APIs? My tentative recommendation is to go with OAth 2.0 client credentials flow.

Although OAuth 1.0 is consistent and widely used, it’s more complex. Furthermore, support for it is already being deprecated by the likes of Google and Facebook.

As to the question of which authorization scheme to use, given the use case, I would be inclined to keep it simple. For instance, you can use an authenticated web session to grant access to the APIs.

On a separate note, I was really surprised by how difficult OAuth is to grok. For some reason I always had this naive view of OAuth as a simple, dev friendly, easy to use protocol. As it turns out, it’s none of those things.

References:

What is 2-legged Oauth?

The Oauth 2.0 Authorization Framework – Internet Draft

The Oauth 1.0 Guide

Getting Started With OAuth 2.0