Securing REST API without reinventing the wheel

jfrobishow picture jfrobishow · Aug 30, 2011 · Viewed 52.3k times · Source

When designing REST API is it common to authenticate a user first?

The typical use case I am looking for is:

  • User wants to get data. Sure cool we like to share! Get a public API key and read away!
  • User wants to store/update data... woah wait up! who are you, can you do this?

I would like to build it once and allow say a web-app, an android application or an iPhone application to use it.

A REST API appears to be a logical choice with requirements like this

To illustrate my question I'll use a simple example.

I have an item in a database, which has a rating attribute (integer 1 to 5).

If I understand REST correctly I would implement a GET request using the language of my choice that returns csv, xml or json like this:

http://example.com/product/getrating/{id}/

Say we pick JSON we return:

{
  "id": "1",
  "name": "widget1",
  "attributes": { "rating": {"type":"int", "value":4} }
}

This is fine for public facing APIs. I get that part.

Where I have tons of question is how do I combine this with a security model? I'm used to web-app security where I have a session state identifying my user at all time so I can control what they can do no matter what they decide to send me. As I understand it this isn't RESTful so would be a bad solution in this case.

I'll try to use another example using the same item/rating.

If user "JOE" wants to add a rating to an item

This could be done using:

http://example.com/product/addrating/{id}/{givenRating}/

At this point I want to store the data saying that "JOE" gave product {id} a rating of {givenRating}.

Question: How do I know the request came from "JOE" and not "BOB".

Furthermore, what if it was for more sensible data like a user's phone number?

What I've got so far is:

1) Use the built-in feature of HTTP to authenticate at every request, either plain HTTP or HTTPS.

This means that every request now take the form of:

https://joe:[email protected]/product/addrating/{id}/{givenRating}/

2) Use an approach like Amazon's S3 with private and public key: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3) Use a cookie anyway and break the stateless part of REST.

The second approach appears better to me, but I am left wondering do I really have to re-invent this whole thing? Hashing, storing, generating the keys, etc all by myself?

This sounds a lot like using session in a typical web application and rewriting the entire stack yourself, which usually to me mean "You're doing it wrong" especially when dealing with security.

EDIT: I guess I should have mentioned OAuth as well.

Answer

Daniel Pereira picture Daniel Pereira · Aug 30, 2011

Don't worry about being "RESTful", worry about security. Here's how I do it:

Step 1: User hits authentication service with credentials.

Step 2: If credentials check out, return a fingerprint, session id, etc..., and pop them into shared memory for quick retrieval later or use a database if you don't mind adding a few milliseconds to your web service turnaround time.

Step 3: Add an entry point call to the top of every web service script that validates the fingerprint and session id for every web service request.

Step 4: If the fingerprint and session id aren't valid or have timed out redirect to authentication.

READ THIS:

RESTful Authentication