HTTP + REST + OAuth = say what???

By Greg Turnquist

Greg L. Turnquist worked on the Spring team for over thirteen years and is a senior staff technical content engineer at Cockroach Labs. He was the lead for Spring Data JPA and Spring Web Services. He wrote Packt's best-selling title, Learning Spring Boot 2.0 2nd Edition, and its 3rd Edition follow-up along many others.

February 23, 2017

In the past couple of weeks, things have really gotten hopping on the Nashville Java community’s #java slack channel. A recent topic topic of interest is how do we take something like REST, which talks about clean URIs and stateless services, and stir in this crazy OAuth stuff?

I threw in my own $0.02 given I’ve done a bit of work on projects like Spring HATEOAS and Spring Data REST. And my $0.02 is this:

HTTP + REST + OAuth should work hunky dory without compromising any of these principles.

What does this even mean?

HTTP is a spec that goes back twenty years. Or should I say, HTTP is an amalgamation of specs that goes back that long. HTTP includes the request/response protocol, the verbs (GET, POST, etc.), the concept of media types, content negotiation, and more. At the heart of MANY of these specs is none other than Roy Fielding. Yes, the man that wrote his doctoral dissertation on REST had his fingers in a dozen specs that governs how the Internet operates.

REST is doctoral dissertation that was published in 2001. REST not a spec, not an API, not a standard. It’s an idea. An idea that if similar constraints that existed for the web plus a few others were adopted when building Internet-based services, then they too could enjoy the scalability and fault tolerance the web has come to enjoy.

OAuth is an 11-year-old security protocol driven by the explosion of 3rd party social media applications that were requiring users enter their credentials so the apps could log into social media networks on their behalf. It introduces a flow whereby the app, instead of gathering credentials, would take the user over to the source site, have them login there, be issued a token, and thereafter use the token in lieu of actual credentials.

All of these concepts have grown supreme in applications today. Enterprise shops want big apps to support millions of customers, and they want them yesterday. Hence the desire for scale.

We’re all aware of how the web was won the war of the UI. I remember coding Swing apps in data centers, and side stepping the growth of the web, but the web has beaten thick client apps hands down. The only REAL thick client app are the apps found on mobile devices. The standards of web apps is front and center.

EVERYONE wants OAuth. I’ve often stated “it isn’t real until it’s secured” indicating that frameworks without a security solution will get passed over by production shops. That’s because no customer will talk to you unless your solution can be secured. And with the rise of mobile apps and multiple clients talking to a backend, the need for OAuth is gigantic.

So how does this mishmash of ideas all fit together without tragic compromise? Let’s take things apart.

Fundamentals of REST

One of the most fundamental concepts behind REST is to include not just data in the payload, but links to resources from which you can DO SOMETHING with the payload. Or links to a state you can transition toward. For example, a Coffee Shop API that let’s you place orders should include a link to cancel the order WHEN IT’S POSSIBLE. By pushing the link to the human user, they can see when they can/can’t do that. Hence the rise of media types that support including links. For example, the JSON document below shows HAL, with both data and links.

{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons/1"
    },
    "address" : {
      "href" : "http://localhost:8080/persons/1/address"
    }
  }
}

That’s nice, but what do we do when this data needs to be wrapped with OAuth?

OAuth, as briefly stated, is a flow where the website redirects the client to a login page, potentially at a different site altogether. A token is issued, and then we go back to the original site. Now we have a token in hand.

This token nicely fits into an HTTP Authorization header like this:

Authorization: Bearer 0b79bab50daca910b000d4f1a2b675d604257e42

If you’ll notice, I said header. HTTP headers don’t infringe upon payloads designed to support REST. HAL doesn’t have to know that the service is protected by OAuth + whatever other security protocols are layered on. Security, as they say, is orthogonal.

That’s because HTTP includes options to extend itself. HTTP has room for new media types (application/hal+json and application/hal+xml), new headers (Authorization), and new payloads.

And why shouldn’t we expect this? The man involved with designing the web also designed REST. Someone trying to take lessons learned from the web and apply them to APIs would surely work to fit it into the nature of the web.

To approach a secured service, I make the call, and if I get a 302 redirect to a login page, my client can come back to the human user and indicate that there is security required. At this stage, it would be completely normal to SHOW the human the login page. Let the user supply what’s needed, and my client should be able to harvest the token, and press on.

Should security be a part of the REST representation?

Yes and no. Security protocols aren’t required to be there. That would clutter up the nature of data and navigation. And clients shouldn’t be giving away any secrets, whether that is a bearer token or credentials.

But hypermedia links should be VERY sensitive to the nature of the client and serve different sets of links based on what the client is allowed to do. If the client will be declined attempting to perform a DELETE, then don’t show them the link to do it.

REST and stateless services

People like to regurgitate this REST-ism about “no state no state no state”. Yet when we get into the subject of security and the STATE of the user’s logged in nature, some people go nuts. Being stateless means that my next REST request should be able to get routed to any server on the backend. In a cloud native environment, there could be twenty copies right now, fifty five minutes from now, and two copies ten minutes after that.

The state of my next REST operation shouldn’t require I go back to the same server. If the server is feverishly trying to push session details around between gobs of servers, that is crazy. That’s why toolkits like Spring Session offer the option to use either cookies or headers. It’s possible to log into a system, get some form of session, offload the session state to a 3rd pary service, like Redis, and then bounce off of that using a header.

As Rob Winch states in the video below, a little bit of state is alright. When done like this, where you security state is managed properly in a data store and NOT on the server itself, you’ll do fine.

So wrap things up, serving up things over the web, securing them with modern practices, while also having scalable APIs should fit together nicely. Because the web was built for flexibility and extensibility, if we just embrace all of its paradigms.

0 Comments

Submit a Comment

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