Implementing Session-Based Authentication with express-session, and connect-mongodb-session

Akhil Anand
3 min readJun 4, 2023

--

Session-based authentication is a widely used mechanism to manage user authentication and access control in web applications. In this article, we will explore how to implement session-based authorization using Mongoose, Express, express-session, and connect-mongodb-session.

We’ll cover the necessary steps to set up the session store, create login and logout APIs, and secure routes based on user authentication.

Prerequisites: Before we begin, ensure you have the following dependencies installed:

  • Node.js and npm
  • Express.js
  • Mongoose
  • express-session
  • connect-mongodb-session

Setting up the Session Store: To store session data securely in MongoDB, we’ll use the connect-mongodb-session package. Start by installing it:

npm install connect-mongodb-session

Now, let’s set up the session store in your Express app. Begin by importing the required modules:

const express = require('express');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const mongoose = require('mongoose');

Next, establish a connection to your MongoDB database using Mongoose:

mongoose.connect('mongodb://localhost/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true,
});

Create a new instance of the MongoDBStore class and configure it to use your MongoDB connection:

const store = new MongoDBStore({
uri: 'mongodb://localhost/myapp',
collection: 'sessions',
});

In the above code, we specify the MongoDB URI and the collection where session data will be stored.

Handle MongoDB connection errors using the error event of the store:

store.on('error', (error) => {
console.error('Session store connection error:', error);
});

Initialize your Express app and configure the session middleware, using store as the store option:

const app = express();

app.use(session({
secret: 'myappsecret',
resave: false,
saveUninitialized: false,
store: store,
}));

In the above code, we set the secret option to a string that is used to sign the session ID cookie. It is recommended to use a long, randomly generated secret to enhance security. The resave option ensures the session is not saved on every request, and the saveUninitialized option prevents empty sessions from being saved.

Then our Express app should look something like this

const express = require('express');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const mongoose = require('mongoose');

// Connect to MongoDB using Mongoose
mongoose.connect('mongodb://localhost/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true,
});

// Create a new MongoDBStore instance
const store = new MongoDBStore({
uri: 'mongodb://localhost/myapp',
collection: 'sessions',
});

// Handle MongoDB connection errors
store.on('error', (error) => {
console.error('Session store connection error:', error);
});

// Initialize Express app
const app = express();

// Configure session middleware
app.use(session({
secret: 'myappsecret',
resave: false,
saveUninitialized: false,
store: store,
}));

Implementing the Login API:
Now, let’s create an API endpoint to handle user login:

const express = require('express')
const router = express.Router()

router.post('/login', (req, res) => {
const { username, password } = req.body;

// Validate user credentials
if (username === 'admin' && password === 'password') {
// Set session data
req.session.isLoggedIn = true;
req.session.username = username;
res.status(200).json({ message: 'Login successful' });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
});

In the above code, we receive the username and password from the request body and perform the necessary validation. If the credentials are valid, we set the isLoggedIn flag and store the username in the session. This information will be used to determine if a user is authenticated or not.

Implementing the Logout API:
To log out a user, we’ll destroy the session:

router.post('/logout', (req, res) => {
// Destroy the session
req.session.destroy((error) => {
if (error) {
console.error('Error while logging out:', error);
}
res.status(200).json({ message: 'Logout successful' });
});
});

In the above code, we call the destroy() method on the session object to remove the session data. Once the session is destroyed, the user is considered logged out.

Securing Routes with Authentication:
To restrict access to certain routes based on authentication, we can create a middleware function:

const requireAuth = (req, res, next) => {
if (req.session.isLoggedIn) {
// User is authenticated, allow access to the route
next();
} else {
res.status(401).json({ message: 'Unauthorized access' });
}
};

// Example of a restricted route
app.get('/profile', requireAuth, (req, res) => {
res.status(200).json({ message: 'Accessed profile page' });
});

In the above code, the requireAuth middleware checks if the isLoggedIn flag in the session is set. If the user is authenticated, the middleware calls the next() function to allow access to the route. Otherwise, it returns a 401 Unauthorized status.

Remember to customize the authentication logic and session management based on your specific application requirements. Feel free to explore additional features like session expiration, session timeout, and persistent login to further enhance your session-based authorization implementation.

--

--