Restful web service authentication

25,700

Solution 1

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 ;-).

Solution 2

There's no reason to not just use HTTP authentication here.

That said, the concept of POSTing to get a time block nonce can work well. But it's the motivations as to why you would need to jump through that extra hoop in the first place.

This technique was considered when using a bcrypt hash for the original password, because of the actual expense of validating a user (if you don't know, bcrypt can be tuned to take significant real time to perform the hash function). The choice was made to provide the option to have the service "log in" once using the password that would go through the expensive validation process via bcrypt, and would then get a time blocked token in return for future requests that would bypass the bcrypt process.

In the case of the bcrypt process, use HTTP Authentication, the service would work with both the normal password as well as with the token. That way the user could always use the password for their service, but it just becomes expensive. So they CAN do this, they just SHOULDN'T. The service doesn't care which authentication technique the client uses.

The nonce service is offered as an aside to improve throughput.

Other than that, it's standard HTTP authentication, but with a new scheme.

Solution 3

Amazon web services does it well, check out there methodology for some ideas. Essentially they get clients to encrypt a special http header using their password.

Here's the link:

http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

Solution 4

Assuming the service is never consumed in a browser and the communication is encrypted anyways, i see no harm in a variation of the second method: Add X-Headers to send username/password with each request, e.g.:

GET /foo HTTP/1.1
Host: www.bar.com
X-MyUsername: foo
X-MyPassword: bar

Another idea would be to use HTTP Basic Auth and just send a Authorization: Basic base64(user:password)-Header. That is, if the connection is always encrypted.

Share:
25,700

Related videos on Youtube

kevin
Author by

kevin

Updated on June 17, 2020

Comments

  • kevin
    kevin about 4 years

    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.

  • Bharat Khatri
    Bharat Khatri almost 11 years
    How do you implement 'login' and 'logout' in such a case ?
  • Cacho Santa
    Cacho Santa over 10 years
    I think that there is no 'login' nor 'logout' in this case, since you are sending username/password in every request.
  • Dobes Vandermeer
    Dobes Vandermeer about 10 years
    One reason not to use HTTP authentication is that the browser will send that automatically with each request, exposing you to CSRF attacks. Using a custom Authorization scheme is OK, though. Or using a custom header.
  • Dobes Vandermeer
    Dobes Vandermeer about 10 years
    Basic Auth is still not as good due to cross-site request forgery.
  • Domi
    Domi about 9 years
    You definitely don't want to send permanent passwords unencrypted. As a general rule of thumb, you even want to minimize re-sending of encrypted passwords, and use temporary tokens (just like session keys) instead.
  • Domi
    Domi about 9 years
    Best answer by any measure. If you could give a good introduction to the algorithm itself here, I'm sure you would get tons of up-votes in no time! I think, one of the most important bits is this: "You first use your secret access key to create a signing key. The signing key is scoped to a specific region and service. Additionally, the signing key expires seven days after creation. Because the scope and lifetime of the signing key are limited, your data is less at risk if the signing key is compromised."
  • felixfbecker
    felixfbecker about 9 years
    If you use sessions on the server your API is not RESTful, because the server has a state. Each request should contain all the necessary data and the server should not rely on sessions. Save your session data in a JSON web token that the client sends in a header on every request. You can pack a serialized user object in there for example (thats how i do it).
  • Chris Nicola
    Chris Nicola about 9 years
    This seems a bit pedantic and also presumes it's important for authentication to be strictly "RESTful". Approaches like JWT do solve this though, if it is either necessary or important for your application to do things this way.