1

I'm looking to implement stateless REST authentication into an API. I've been reading up on articles here, and have implemented an idea that works, but I was hoping to get some feedback on its security, and any potential improvements.

  1. Initial authentication happens over HTTPS Basic Auth. Username and password are provided in plaintext.

  2. The server generates and provides a token that is provided to the client, but is not stored in the database. All articles I've read on auth tokens suggest storing not the token itself, but some value that can be hashed with another value (the username, etc.) to generate the token again and validate - but I thought the point of a REST API was to be stateless, and not store any tokens/values related to the auth?

  3. This token is then used for subsequent requests in place of always requiring the username/password in the headers.

The Token

The token is generated using:

encrypt(username, salt, hash, expirationDate)

Where encrypt is reversible using currently a DES Cipher, but in the future possibly a private key or server-stored resource that can be easily replaced without relying on a value in source code.

The benefit is that this allows the server to decrypt the incoming token, and compare the salt/hash against what is stored in the User model object. (Which has salt and hash properties stored in the database.)

The concerns I have with this:

  1. If the private key or Cipher password are known, these tokens can be spoofed.

  2. I've considered using password instead of salt and hash, but I didn't like the idea of the password being known if the private key or Cipher password is found.

So: Is there a better way to do this kind of "decryptable" token authentcation? And, is it worth maintaining this "stateless" goal of REST, or should I just be storing some hashed version of the token and username (but not the token itself) in the database and throwing the "stateless auth" idea out the window?

2

I think you misunderstood the "stateless" constraint from REST. From what was written in Dr. Fielding's dissertation, one can get a wrong impression that stateless means not to keep (server-side) any information about the client, which is wrong. What was meant was that the server shouldn't keep anything related to the client's session (state of the client, that can change during its servicing), which is a different thing.

For example, if your web service should support multiple users you should keep the information about your users, along with their credentials, so that you can validate each request and confirm that it comes from a valid user from your system.

What you shouldn't keep is the state a user is in, while using your service. Take a look at this sentence from the dissertation:

Scalability is improved because not having to store state between requests allows the server component to quickly free resources, and further simplifies implementation because the server doesn't have to manage resource usage across requests.

So, if you store the state of your clients on your service machine, your storage limits might be reached quickly, with each new user added to the system, not to mention the scenario where a single user can have multiple concurrent requests and you have to manage resources across each of those requests. Also, if one of your service machines go down, any other available service machine won't be able to just take over that client and continue servicing him, because the state of that client, that was being kept on the failed service machine is lost.

Long story short, you don't really need sessions for REST services. Just make sure that your communication is secured (HTTPS) and you can send the basic auth info with each request. If you are really concerned with security, try using hmac or oauth or even per-client certificate. But make sure that you don't store any sessions on your service machines.

Do note that this doesn't mean you can't use external authentication services, which don't need to be RESTful, like single-sign-on servers.

0

Hopefully you mean 3DES, or maybe DES was a typo and you mean AES? Single DES can be easily cracked these days.

Anyway, why do you need it to be decryptable? A reasonable pattern for generating an authentication token would be something like this pseudocode:

raw_token = userid + ':' + expiration_time
sig = HMAC(raw_token, service_key)
token = raw_token + ':' + sig

Then, when a request is received, you can verify the token by splitting off the signature, recomputing and verifying the HMAC, and then checking that the expiration time has not passed.

Yes, much like you describe, this has the property that if the key becomes known, it is possible to forge tokens. This would be inherent to any system that uses cryptographic tokens for authentication, and about the only alternative is the "generate a random token and store it server-side as well" pattern.

  • Thanks David. The token creation portion is a proof of concept still, nothing in production - so we'll certainly be using a more secure algorithm, should we go the decryptable route. We're using Spring Security (I will update my Q to address this) and was basing my attempts on this answer: stackoverflow.com/a/10864088/88111 The idea of having a service_key that is constant and "knowable" is a little discerning, so I may go the persisted token route so any breaks would require DB access, which seems a little harder than knowing the key? – Craig Otis Oct 5 '14 at 13:34
  • 1
    The key can be generated when the server starts, by for example reading some bytes from /dev/urandom. If you do this you wouldn't store your key anywhere and it would only exist in memory for the lifetime of the server. – Fors Jun 2 '15 at 8:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.