I'm working on a social network using Vue.js on frontend, and Node/Express on backend. To store user sessions I'm using Redis. I'm wondering if I should hit Redis everytime user requests content, or maybe there is a way to reduce the load?
Are you sure this is necessary? Redis should be pretty fast, have you done performance tests?– AndrolGenhaldJul 6, 2018 at 14:09
Application login session management is NOT a security question, it is more like a programming question. (I didn't downvote)– mootmootJul 6, 2018 at 15:11
2I think this is a great question. Security is absolutely part of programming, sys admin and network engineering. Oh and policy and hr...– Joe MJul 6, 2018 at 17:31
You should be using session management to handle information transfer between clients and servers.
Session management essentially involves authenticating a user to initially perform a privileged action, with all subsequent activities being authenticated via 'shared' information eg: cookies.
Asking users to authenticate for each and every action might be considered more secure but will heavily reduce platform usability and overall user satisfaction as a result.
With regards to database load, without seeing the specific application I can't be 100% however I would advise as long as you are logging the last time the session was used, you don't need to write much other information to the database.
1Just to elaborate... one of the ways sessions can be authenticated is with a digitally-signed cookie. Most frameworks have something like this built in. Verification that the session is authentic can be done with crypto up-front, saving a database (or cache) hit. You'll still want a session store in the database or some other server-side store to keep internal secrets and details from leaking into the browser's cookie storage.– nberingJul 6, 2018 at 14:13
Claim-based identity is a good way to reduce the load of authenticating a user.
The simplest way to implement that is to have a first authentication portal that generate signed tokens containing the necessary claims for the user and then have the subsequent call require that token, verify the signature and, trust the claims.
See JWT for a practical implementation.
It should be noted that this makes it impossible to force session expiration while a JWT is still valid. Jul 6, 2018 at 14:02
Correct. There are ways to mitigate this (adding an ID to the token and propagating a list of invalidated tickets to all system that will need to validate) but it's something that adds complexity and potentially lowers perfs.– StephaneJul 6, 2018 at 14:14
Indeed, if you're checking redis for a blacklist on every connection, you might as well just do sessions the normal way. You could propagate the blacklist to each system, but that's more complex. Jul 6, 2018 at 14:18
Ah no: authenticating the user is really NOT the same as checking if the session is part of a specific set of expired sessions. First, if you store your credentials properly, it is likely to be waaay faster and cheaper. And even if you don't, it can be optimized in many different ways (because it's a dataset of limited size, doesn't contain any confidential data, only needs to be propagated once per record and in one direction and each record has a very limited lifetime). It's really not that hard to implement in a secure and efficient way even for larger systems.– StephaneJul 9, 2018 at 6:54
Hmm, yes, that is a bit of a weak argument isn't it? I'm not arguing for authenticating the user's credentials on every request though, just for using a central storage for standard sessions. Jul 9, 2018 at 13:16
This is really somewhat off-topic here. We don't know what your application is/does/looks like - so we can't answer the question you asked beyond saying that the functional relevance usually overrides the performance consideration. However since others have already started answering....
Traditionally, http sessions use a random identifier sent to the client which is a key to data on the server. Each time a request requires session data, this is read from the storage. And in most implementations it is subsequently written back to the storage on or before completion of the request. The latter is important to update the timestamp on the session so it can be garbage collected later. Now you definitely want to write the data back to storage when it has changed, but writes are at least 3 times as expensive as reads. So even though you can implement this without impacting delivery of content to the client, not writing unchanged session data back to the storage with every request can have a big impact on capacity.
Using a faster storage substrate can help too.
Then there's the possibility of caching content. Some content needs to be generated afresh each time its accessed. Some content will be near static for a given user, and some content will be the same for all users. HTTP provides mechanisms for advertising this fact to the client and to a reverse proxy. For example, for content cacheable by a specific user, you could incorporate the user id in the Etag - but remember to add a cache-control:private header at the point where it leaves the reverse proxy.
Although you generally can't trust content sent from the client, you could encrypt the data in cookies and use the client for storage - and check for tampering when you decrypt it. Again, this is about capacity rather than performance. And some thought needs to be applied to persistence of the data on the client, even if it is encrypted.
But, except in a very few cases, the performance overhead of sessions, relative to everything else going on in a web page is very, VERY small.
It looks like you are rolling your own authentication or at least a part of it.
I'm wondering if I should hit Redis everytime user requests content,
Yes you have to check the user session against your backend storage on each http request, this a how web servers and web frameworks deal with user sessions, some of them use filesystem to store sessions like Apache and others use relational DB like Django Framework does by default.
In-memory storage like Redis and Memcached is de facto the right choice for such case.
However you can still increase the performance by reducing the number of roundtrips between the client and your server this can be achieved by aggregating data to smaller numbers of request which will decrease in hit frequency on Redis.
No, you don't need to hit Redis on every request is the answer, as you can manage sessions from your backend by issuing a secure cookie. Imagine what would happen if facebook or twitter would hit their db on every request user makes? Additionally to this it would slow down users request.
The cookie provides the means to authenticate/authorize; whether or not you need to check against the back-end's system of truth depends on the scenario. A secure system does need to check to see if the user's auth is still valid, e.g., if I terminate an employee, they should no longer have access to company systems: I cannot rely on the client's (e.g., browser) version of truth to secure my system. In general, DBs (or a caching layer) are hit on every request, that's how the back end knows what to send back. Jul 7, 2018 at 11:38