Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stateless login/authentication mechanisms for scalable web applications?

I'm trying to understand the options that I have when creating an authentication mechanism for applications that can run on an arbitrary amount of web servers. Until now, I only have experience with small websites that use (web-)server-side sessions to manage the aspects of authentication. But as soon as I want to add more web servers (or "web instances" in PaaS environments), this approach obviously becomes a problem; authentication state that is bound to specific machines is from my understanding not what you want when using load balancing (afaik sticky sessions/sticky load balancing is something that should be avoided). I'm looking for a solution that allows me to scale the number of web servers/instances up and down dynamically without having to take care of the authentication mechanism.

I think the only way to achieve this is to take session/authentication state out of my web servers. This is what I meant by saying "stateless". Of course that state has to be temporarily stored somewhere, so there must be something that is not stateless.

I could use a database server to manage all of the auth sessions. The database server could be accessed from all of my web servers on each http request to ask for the authentication state of users. But since database servers are even harder to scale than web servers (that would be my assumption without having any experience with it), I would just move the problem from web servers to database servers. Apart from that, I don't think it would be the best solution in terms of performance.

Instead of a database server, I could maybe use a cache server like memcached or redis to manage the sessions for authentication. I think this would minimize the scalability problems since a single cache server could manage a lot of sessions in a performant way (or am I wrong at this point?). But I sometimes read things like "an important point about the cache is that it behaves just like a cache should: the data you just stored may just go missing.". Well, this would be a problem. I don't want users to have to login every 2 hours. My question is: why would data in a cache go missing if the cache has enough memory? Wouldn't 250MB of memory in the cache server be enough to manage over a million sessions at the same time without having to get rid of data (when using simple key-value pairs mapping session ids to user ids or the other way round)?

A third solution might be to store the auth sesson state in cookies that are signed by the server and can not be manipulated by the clients. But if I am not wrong, there is no way for the server side to enforce the logout of a certain user...

To sum up my requirements:

  • I want to scale web servers behind a load balancer up and down and the auth system should deal with it

  • Users should be allowed to be logged in for at least several days
    like e.g. on stackoverflow.com

  • The server side should be able to log users off if there is a reason to do so

I'm interested in best practices. I think there are a ton of websites that face the same problems and found solutions for it.

like image 537
apptio Avatar asked Jan 20 '14 10:01

apptio


1 Answers

This github project is a good place to start. Implementation is in the Play! Framework, but its a good explanation for what I think you're after. Also helps overcome CSRF that could be inherent in the app.

The server sends back an auth_token (via https) after login. The auth_token is saved as a cookie (just so it will be persisted and accessible from client). When a request is made the auth_token is placed as an HTTP header (via JavaScript) that was saved in the cookies. Then its pulled off by the server request handler and validated with each request. So its a cookie -- but not used as a cookie. A "twice baked" cookie if you will :) The links explain more in detail.

And another answer here on stack overflow I found explains a very similar thing. A "session without a session."

And then if you really want to dig into it check out owasp.org on CSRF prevention, which explains a similar technique under the heading "General Recommendation: Synchronizer Token Pattern"

All communication should be HTTPS.

like image 144
Tom Avatar answered Nov 09 '22 02:11

Tom