Restful web service authentication

authenticationrestrestful-authenticationweb services

I have a Restful web service API, that is being used by different 3rd parties. Part of that API is restricted (you need username/password to access it). I was wondering what would be the best way of implementing authentication?

I'm using https, so communication is encrypted. I have two ideas:

  • Before user starts using (restricted) service, it sends username/password using POST (since https is being used credentials are encrypted). After the login is successful, server sends back random single-use value (nonce) that is matched with this username. When next request is being made, along side a username, client sends previously returned nonce. Servers matches username and nonce and returns new nonce along side requested data. Each new request uses new nonce. Basically, this is a lightweight version of Digest access authentication.
  • Since this API is used from 3rd party, username/password could be used for each (restricted) request. Since https is being used, they will be encrypted. Downfall of this approach is the fact that this wouldn't be Restful compliant (POST would be used always).

I'm much closer of choosing first approach (it is Restful compliant, relatively easy to implement, XML, json or html can be used without changing anything), but I wanted to see what is your opinion? What do you recommend: first, second or some third approach?

Btw, I'm using Python at server side.

Best Answer

One way I've seen this done in APIs (and the way am currently implementing it) is to create a RESTful resource called Session which is created via a POST which supplies a username and password.

Here is basically how I've implemented it:

POST /sessions { Username: "User", Password: "Password" }

Create an time limited session and returns the session resource which contains the session key value and expiry. You may also want to return this as a cookie value for the convenience of implementation of API clients.

DELETE /session/{id}

Immediately expires the session so it can no longer be used. This is used for explicit sign-outs.

I then have the user attach the session key via a query parameter, though you can also allow it to be submitted via a cookie value, I'd recommend allowing for both.

What I prefer about this is that it is extremely simple.

Obviously your scenario will dictate somewhat how your sessions should be managed, perhaps they are not time limited and last indefinitely, and perhaps they are hashed or encrypted for added security.

If you are using HTTPS everywhere you probably don't need to worry too much. However, if you want to use HTTP, you will need to use something like a hash along with a secret key and say a time stamp to generate a secure key per request. This way you can share the secret key over HTTPS and then switch to HTTP for further calls. Even if someone manages to sniff out the key from a request it can expire almost immediately and be useless.

Disclaimer: I am not a security expert ;-).