Information Security
web-application authentication databases cookies session-management
Updated Mon, 18 Jul 2022 15:19:53 GMT

avoid hitting DB to authenticate a user on EVERY request in stateless web app architecture?


Summary

Once a user logs into a web site and his username/password credentials are verified and an active session is established, is it possible to avoid hitting the DB for each and every request from that user? What is the recommended method of securely authenticating subsequent requests for the life of the session, while minimizing DB queries and other internal network traffic?

Background

In a stateless web app server architecture, where each request has no knowledge of any prior activity from the user, it would be necessary to query the DB on each and every request from that user (typically by querying the session ID stored in a cookie and transferred in the request header). But what if some basic information was encrypted and stored in that Session cookie that had enough information to validate the user for non-sensitive, non-editable requests? For such requests, you could as an example encrypt and store the user ID and something that uniquely identifies his machine as much as possible (user-agent + ip address) in the Session data. The key used to encrypt the data could change daily making it difficult for any hacker to clone the Session data on a different machine. When the Session expires you would need to fully validate the user's credentials. The fact is, the biggest threat to hacking a user's session would be someone using a user's computer that he or she left unattended. Should I just not worry about this and let some level of caching between the web app servers and the DB take care of expediting the authentication process? While it may seem to be unnecessary optimization, it seems like a candidate ripe for improvements in efficiency since each and every request requires this process. Thanks for any suggestions!




Solution

Yes it is possible, and this technique is widely used.

It does have some minor drawbacks compared to stateful sessions:

  1. It does not support strong logout. If a user clicks logout, the cookie is cleared from their browser. However, if an attacker has captured the cookie, they can continue to use it until the cookie expires.
  2. The use of a server-side secret to create the tokens creates a single point of failure: if the secret is captured, an attacker can impersonate any user.

Deciding whether to use stateless or stateful sessions depends on your performance and security requirements. Online banking would tend of use stateful sessions, while a busy blog would tend to use stateless sessions.

A few tweaks are required to your proposed scheme:

  1. Encrypting the token does not protect it from tampering. You want to use a Message Authentication Code (MAC) which does protect tampering. You may additionally want to use encryption, but that is less important.
  2. You need to include a timestamp in the token and put a time limit on their validity. Somewhere around 15 minutes is sensible. Normally you would automatically re-issue shortly before the timeout, and usually the reissue would incur a database hit (although even that can be avoided)
  3. Do not include the user's IP address in the token. Approximately 3% of users will legitimately change IP address during a web session, due to modem resets, changing WiFi hot spots, load balanced proxies and more. While you can include the user agent in the token, it is not normal to do that - consider it an advanced technique to use if you are sure you know what you're doing.
  4. If an attacker captures a session cookie they can impersonate that user. There is nothing you can really do about. Instead, put all your effort into preventing an attacker capturing the cookie in the first place. Use SSL, use the "secure" cookie flag, fix all cross-site scripting flaws, etc. And have some user advice to lock their screen when their computer is unattended.

I hope this is helpful to you. If anything is unclear or you need further information, leave a comment and I will see if I can help you further.





Comments (5)

  • +1 – Thanks for your helpful answer. In regards to your 2nd concern, I would change secrets on the server very often. In fact, wouldn't it be possible to change secrets say every 15 minutes in lieu of a timestamp to time out a token? If a token is sent that is using an old secret it would be invalid, necessitating a full login by the user. You could validate a token that uses both the current secret and the prior one (to allow seemless reissues). Anything else would be invalidated. — Jan 22, 2014 at 17:13  
  • +1 – Regarding #3 where'd you get the 3% stat from? I'd like to read up on that. — Jan 22, 2014 at 18:42  
  • +1 – @SteveS original research I did using my website. It is old, but I expect the figure is still broadly correct. It's written up in this paper: westpoint.ltd.uk/advisories/Paul_Johnston_GSEC.pdf — Jan 22, 2014 at 21:42  
  • +0 – @onlinespending Changing the server secret every 15 minutes... interesting idea. I've not seen it implemented - most sites simply accept the risk - but I think it could work. — Jan 22, 2014 at 21:43  
  • +1 – @onlinespending I've not looked at how Facebook do it, but I expect the "remember me" cookie is stateful and requires a database access to verify, while the session cookie is stateless. Actually, I've not looked at many sites in detail that use stateless cookies - most clients that commission pen tests are security sensitive and go down the stateful route. Facebook may well be fully stateful, as every page load requires database access anyway, so it may be little performance hit for them. — Jan 22, 2014 at 22:26