- Express.js Basics
- Express.js HOME
- Express.js Introduction
- Express.js Installation
- Express.js Basic App
- Express.js Routing
- Basics Routing
- Route Parameters
- Handling Query Strings
- Router Middleware
- Middleware
- What is Middleware?
- Application-Level Middleware
- Router-Level Middleware
- Built-In Middleware
- Error-Handling Middleware
- Third-Party Middleware
- Express.js HTTP
- Handling GET Requests
- Handling POST Requests
- Handling PUT Requests
- Handling DELETE Requests
- Templating Engines
- Using Templating Engines
- Setting Up EJS
- Setting Up Handlebars
- Setting Up Pug
- Request/Response
- Request Object
- Response Object
- Handling JSON Data
- Handling Form Data
- Static Files
- Serving Static Files
- Setting Up Static Folders
- Managing Assets
- Express.js Advanced
- Middleware Stack
- CORS in Express.js
- JWT Authentication
- Session Handling
- File Uploads
- Error Handling
- Databases
- Express.js with MongoDB
- MongoDB CRUD Operations
- Express.js with MySQL
- MySQL CRUD Operations
- Deployment
- Deploying Express.js Apps to Heroku
- Deploying Express.js Apps to AWS
- Deploying Express.js Apps to Vercel
Express.js Session Handling
In the world of web development, HTTP is a "stateless" protocol. This means that every time a client sends a request to a server, the server sees it as a brand-new interaction with no memory of what happened before. To build features like user logins, shopping carts, or multi-step forms, we need a way to "remember" the user. That is where sessions come in.
Session handling in Express.js allows you to store specific data about a user across multiple requests. While a cookie is stored on the user's browser, the session data itself lives on the server, making it a much more secure way to handle sensitive information.
Key Features of Session Handling
- State Management: It bridges the gap between independent HTTP requests, allowing you to track a user’s journey through your site.
- Secure Storage: Because the actual data (like a user's database ID or role) stays on your server, it is much harder for malicious users to tamper with it compared to client-side cookies.
- Customizable: You can decide how long a session lasts, where it is stored (RAM, Redis, Database), and how the cookie is configured.
- Simple API: By using the
express-sessionmiddleware, the complex logic of generating IDs and setting headers is handled automatically, leaving you with a simplereq.sessionobject to work with.
Setting Up Session Handling in Express.js
Install the express-session Middleware
Express does not have built-in session management. You need to install the official middleware package to get started.
npm install express-session
Basic Session Configuration
To use sessions, you must register the middleware in your Express application. This configuration tells Express how to sign the session ID and whether to save the session back to the store even if it wasn't modified.
Example:
const session = require('express-session');
app.use(session({
secret: 'keyboard_cat', // A unique string used to sign the session ID cookie
resave: false, // Don't save session if unmodified
saveUninitialized: false, // Don't create session until something is stored
cookie: {
maxAge: 60000, // Session expires in 60 seconds
secure: false // Set to true only if using HTTPS
}
}));
secure: true while testing on local http://localhost. If you do this, the session cookie will never be sent, and your sessions will appear "broken" because they require an encrypted (HTTPS) connection.
Storing and Retrieving Session Data
Once the middleware is active, you can access req.session in any route handler. This object is where you can store any data you want to persist.
Example:
// A mock login route
app.get('/login', (req, res) => {
// In a real app, you'd verify credentials here
req.session.user = {
id: 1,
username: 'JohnDoe',
role: 'admin'
};
res.send('You are now logged in and your session is active.');
});
// A protected route
app.get('/dashboard', (req, res) => {
// Check if the session contains user data
if (!req.session.user) {
return res.status(401).send('Please log in first.');
}
res.send(`Welcome back, ${req.session.user.username}! Your role is: ${req.session.user.role}`);
});
Destroying a Session
Logging out is essentially the process of deleting the session data on the server and clearing the cookie on the client. You do this using the destroy() method.
Example:
app.get('/logout', (req, res) => {
req.session.destroy(err => {
if (err) {
return res.status(500).send('Could not log out at this time.');
}
res.clearCookie('connect.sid'); // Optional: clear the cookie by name
res.send('You have been logged out.');
});
});
Using a Session Store
By default, express-session stores data in your server's RAM (MemoryStore). This is dangerous for production because if your server restarts, everyone is logged out. Additionally, it causes "memory leaks" as the number of users grows. For real-world apps, use a store like Redis.
Example with connect-redis:
npm install connect-redis redis
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
// Initialize Redis client
let redisClient = createClient();
redisClient.connect().catch(console.error);
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'super_secret_production_key',
resave: false,
saveUninitialized: false
}));
Complete Example
Here is a complete, production-ready structure for an Express app using sessions with a Redis backend.
const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const app = express();
// 1. Setup Redis Client
const redisClient = createClient();
redisClient.connect().catch(console.error);
// 2. Configure Session Middleware
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET || 'dev_secret_key',
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // Set to true if using HTTPS/SSL
httpOnly: true, // Prevents client-side JS from reading the cookie
maxAge: 1000 * 60 * 30 // 30 minutes
}
}));
// Mock Login Route
app.post('/login', (req, res) => {
// Logic to verify user...
req.session.user = { username: 'JohnDoe', role: 'admin' };
res.send('Login successful');
});
// Dashboard Route (Protected)
app.get('/dashboard', (req, res) => {
if (!req.session.user) {
return res.status(401).json({ error: 'Unauthorized' });
}
res.send(`Hello, ${req.session.user.username}. Accessing admin panel...`);
});
// Logout Route
app.get('/logout', (req, res) => {
req.session.destroy(err => {
if (err) return res.status(500).send('Error during logout');
res.send('Logged out successfully');
});
});
app.listen(3000, () => {
console.log('App listening on http://localhost:3000');
});
Summary
Session handling is a fundamental skill for any Express.js developer. By moving from the default MemoryStore to a persistent store like Redis and properly configuring your cookie security settings, you can build applications that are both user-friendly and highly secure. Remember to always handle the session lifecycle—from creation during login to destruction during logout—to keep your users' data safe.