Node.js › Authentication & Authorization

How does session-based authentication work in a Node.js/Express application, and what does the session store need to handle?

Intermediate

Answer

In session-based authentication, after a successful login the server creates a session record (containing the user's identity and any relevant data) stored server-side, and sends the client only an opaque session ID via a cookie -- each subsequent request includes that cookie, and the server looks up the corresponding session data before processing the request. The session store (in-memory for development, but Redis or a database in production for scalability across multiple server instances) needs to handle expiration, and in-memory stores don't work correctly once an application is scaled horizontally across multiple processes without a shared store.
const session = require('express-session');
const RedisStore = require('connect-redis').default;

app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET,
  cookie: { secure: true, httpOnly: true, maxAge: 86400000 },
}));

app.post('/login', (req, res) => {
  req.session.userId = user.id; // stored server-side, keyed by the session ID cookie
  res.json({ success: true });
});
Real-world example A service running three load-balanced instances of the same Express app switches its session store from the default in-memory store to Redis, since a user's session previously only 'existed' on whichever specific server instance happened to handle their login request, causing random logouts when subsequent requests hit a different instance.

Common follow-ups: Why is httpOnly on the session cookie an important security setting?;What specifically breaks about in-memory session storage the moment an app is scaled to multiple processes or servers?