views:

751

answers:

3

Today I implemented a session/token authentication system for my web api (http get/post rpc style), following this plan:

legend: action (param1, param2) : returnvalue1, returnvalue2

  • login (username, password) : sessionkey, token
  • requestA (sessionkey, token, paramA) : token
  • requestB (sessionkey, token, paramB) : token
  • logout (sessionkey, token) : void

The login action is sent over https, to protect the users data. You get a session/token combination, where one token is only valid for one request (you will always receive a new token on normal requests). My thoughts behind this were about reducing the risk for a man-in-the-middle attack, sniffing your session key: if you are "lucky", the sniffed token has already been invalidated through your own subsequent request.

My backend and its unittests are perfectly fine, but i didn't think far enough - i finally ran into issues with asynchronous ajax calls, which defeat this one-time-token idea.

Is the added security worth not being able to process asynchronous requests?

One idea was to introduce a request-queue inside my ajax application - did someone do anything like that, and would you recommend it?

A probably less secure, but more convenient way would imho be not to renew the token for every request - allowing asynchronous processing, but keeping the initial https auth and add a strict lifetime to a session. I should also save the IP to the session server-side.

Did i miss other valuable options?

I am bound to existing username/password values, which with no exception have to work without changes with the new ajax app.

+1  A: 

It appears to me that the token mechanism that you designed won't actually protect you from man-in-the-middle attacks. Imagine a man-in-the-middle intercepting every (non-HTTPS) request from the client, and replacing it with a different one that is then sent to the server. The token that the server returns to the man-in-the-middle can then simply be returned back to the client, and the client probably would not be able to tell that its request never arrived at the server.

Is there a way you can simply do all the requests over https? Https offers a fair amount of protection from man-in-the-middle attacks, provided that you use proper certificates, and use highly random session keys that are not valid for too long.

molf
+1  A: 

Any subsequent requests after authentication that are made in plain text (read HTTP) should be considered insecure and prone to any attack you can imagine.

If your goal is to secure the communication between the client and your server HTTPS is a must for the whole session. Additionally you will want to make sure you change the session cookie after the client moves from HTTP to HTTPS (I'm assuming here that you are doing some sort of redirection if the original request is to HTTP). This is a common error that leaves the client vulnerable to a session stealing attack.

Rails does something similar to the mechanism you are describing. They call their tokens authenticity tokens. However my understanding is that the primary purpose is to do flow control or double-click protection instead of actually securing the communication.

Kam
+1  A: 

I think HTTPS and binding the Session to the clients IP and regenerating the session id from time to time (maybe every 5 requests) will secure your API. Adding the request/token mechanism will improve security, but is no longer a must have, imho.

One problem I see upcoming with the request/token system is, if a request failed or no answer is recieved, how can the client restart communication? It has no valid request token and if your API works correctly, it will reject any request following :)