Is OAuth Stateless? Can it work for REST?

I spent a good chunk of the last year putting together a couple of different implementations of OAuth for internal use by our web services, and for some admin UI interfaces. The architecture guys were trying to push other development teams besides ours in that direction, too, so that we could have our services inter-operate, with a single security model.

Because I work in a large, multi-national corporation, nothing is that easy. There was lots of push back, and lots of opinions about how we should provide authorization around our web services and pages.

Or… lots of monkeys getting passionate about how to peel their bananas.

But one complaint that was kind of annoying was a standard rallying cry of the detractors that OAuth is not stateless. Ergo, it violates the principles of REST, and, ergo, is not consistent with the overall architectural direction.

So here is my take on that. I’m interested in what others think.

First, if the architecture team says, use REST, and then later they say use OAuth, it’s kind of silly to say the one rule disqualifies the other. Every technical choice is a series of considerations, and, one way or another, at the end of the day authorization and security concerns are going to trump just about anything else.

Second, how can you complain about OAuth’s state-ish-ness, and then turn around and put SSL in front of a REST service? I mean, come on.

However, ultimately, I’d like to come up with a better answer than “stop whining”, so I’ve been noodling on it some. Here’s what I think.

While the OAuth protocol is not stateless, because it requires the user to pass credenitals one time, and then maintain state of the user’s authorization on the server side, these are not considerations of the underlying HTTP protocol. It’s a higher-level concern. It’s the same as passing a “login” cookie or some other session token so the server can keep track of the user. Which is something we do all the time.

The point of statelessness is to make the servers on the REST side anonymous — so you can bring them up or tear them down at will, and leave the health of your service intact. If I have information held for clients on a particular box, and it goes down, then I have a problem, because all the client interacting with that box have lost their state.

But the kind of state that OAuth maintains is above the level of the HTTP protocol, and represents a generalization of an application concern. So really it’s not the individual *server* that cares about your OAuth token, it’s the *application* that cares.

Which means you can push your OAuth token into a distributed cache like memcached, and your individual servers are safe. OAuth, while it requires a sort of “session” state, doesn’t affect the state of any particular server, and doesn’t force you to provide server affinity.

In other words, yes, OAuth is stateful, but not the way you’re worried about. It doesn’t require the RESTful servers to be stateful.

In our implementation, we really quickly gave up on providing OAuth as a solution inside the application code itself, and almost all of our REST services externalize OAuth. For incoming traffic we use a reverse proxy in front of the service, and on the way out we use a regular proxy going to remote services. The “in” guy provides validation and bounces any unauthorized requests before they get to the REST server. The “out” guy adds the necessary headers to any outgoing request to satisfy OAuth.

That’s even nicer than terminating SSL in our load balancers, and I don’t hear anyone complaining about that.

I suppose I’ll have to continue scowling at the smug faces of developers who are convinced they’ve defeated OAuth with logic, but really I don’t see a problem with OAuth in a stateless server world.

Probably there’s a more concise way to put it, though, and I’d love to hear that.

So, to be clear, OAuth works well with REST, and doesn’t compromise any REST-ful-ness requirements for a server.

There are two ways to look at it:

+ authorization is part of the application concern, and part of a resource definition. Remember that the definition of Resource is arbitrarily large. So, “A list of ___ as allowed in this authorization scope.”

…or…

+ as a transparent concern provided by middleware, exactly as SSL (or even TCP) is. SSL doesn’t compromise the statelessness/REST-ful-ness of a service, despite it’s stateful protocol. One of the fundamental ideas of REST is to line up services in a way that allows dropping middleware in the flow to take care of concerns like routing, load balancing, encryption, authentication and authorization, without compromising the reliability of scalability of a resource server.

So OAuth, or really any token-passing authorization scheme, doesn’t compromise the validity of a REST service that it protects. You aren’t required to use Basic Auth, or proscribe SSL, everywhere to defend the REST-ful-ness of your service.

(However, statelessness is a good idea in itself … but the bigger issue for REST is that very few teams are implementing hypermedia in their service, so hardly anyone is implementing REST anyway.)

Advertisements

4 Comments

Filed under OAuth, REST

4 responses to “Is OAuth Stateless? Can it work for REST?

  1. Pingback: This Week in #REST – Volume 29 (Nov 2 2010 – Nov 20 2010) « This week in REST

  2. I think, it is a good design choice to move OAuth handling out of the application code. This is similar to what one would get if they use API management solutions like the ones offered by apigee

  3. Alex

    OK, so here is how I see it:

    HTTP is a stateless protocol, which means it does not retain the state of the conversation that transpires between the client and the server. Each request arriving at the server must contain all information necessary for the server to process that request correctly. We call that information in-band (meaning, the server must not ask subsequent questions before it is capable of processing the request).

    So, when it comes to authenticating the incoming request, the server should not be expected to retain the knowledge that, yes, this client has already been authenticated. This means that each incoming request appears to the server as if coming from that client for the first time ever, even if it’s the hundredth request coming from that client in the past 10 minutes. So how to solve that?

    A super naive way would be to insist that the user re-enters their credentials each time they’re sending a request. That, of course, is utterly unacceptable, because it is utterly disrespectful to the human user etc. Imagine having to retype your username and password hundreds of times while conducting some transaction — e-commerce would have never taken off if that were the case.

    To circumvent that, HTTP offers equally stateless facility known as Basic Auth. What Basic Auth does is instructs the client browser to cache the username and password once the user provides those credentials and they get cleared. From that moment on, each subsequent request travels to the server with encrypted username and password, which relieves the user from having to retype those over and over again.

    So authentication using HTTP is fully stateless, because the server receives, via the Basic Auth, all in-band information necessary to authenticate the request.

    This mechanism. however, doesn’t work for headless API services, nor does it work for OAuth. We need different facilities to enable headless API authentication and OAuth. However, I disagree with the author of the article that OAuth is not stateless. I’ve implemented stateless OAuth before. All it takes, once the user gets authenticated, is to fabricate a secret authentication token and hand it over to the client. The client then holds on to the secret authentication token and sends it back with each subsequent request. As long as that token hasn’t expired on the server side (expiry is governed by the company’s internal security policy), the user request gets authenticated and cleared.

    Same goes for authenticating via Facebook — we obtain clearance from Facebook, we then either find that user on our records or insert a new one, and then take it from there. Fabricate our own home grown secret authentication token, pass it on to clients, and then expect to get it back with each subsequent request. If the token matches, the request is cleared. Otherwise, 401 Unauthorized.

    • jeje

      Except even with Basic Auth, the password needs to be stored somewhere. Client and server need to agree. Similarly, in OAuth2, the access token is all the request needs to contain for the request to move forward. So it’s a matter of exchanging a long-lived credential (password) for a short-lived one (access token), but the mechanics remain the same.

      Excellent reply, thank you. I think you stated the proposition better than I did.

      BTW really, really sorry it took me so long to approve. I switched email accounts have haven’t checked this one in a while (!)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s