Creating and managing sessions in ExpressJS

In ExpressJS sessions can be managed easily.

In Node.js sessions work at application level. When you initialize a session handler object as a middleware in ExpressJS, the request object will share an instance of such handler with all the routes of your application.

The express-session module works in this way. Once a session handler has been created, we can add or remove session variables by simply manipulating a JavaScript object.

Though this module uses the server's memory as its default storage mechanisms, it's often preferable a database-based approach on a production environment due to the volatility of the default mechanism. For example, it becomes difficult to track user actions or, say, to save a shopping cart for later use when your session data are stored in memory. When you restart your app, all data saved in memory are gone forever.

We can use MongoDB as session storage. First, we need to include the requested modules.

npm install express-session --save
npm install connect-mongodb-session --save

In MongoDB we need to create a collections for our sessions. For the sake of simplicity we can call it sessions. Then we can reference the newly installed modules in our app.

'use strict';

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

Configuring the MongoDB store is simple: just pass the database connection URL and the name of the collection to the constructor.

const store = new MongoDBStore({
    uri: 'mongodb://username:password@127.0.0.1/test',
    collection: 'sessions'
});

At this point we can set up our session middleware.

const app = express();
app.use(session({
    secret: 'secret token',
    resave: false,
    saveUninitialized: true,
    unset: 'destroy',
    store: store,
    name: 'session cookie name',
    genid: (req) => {
        // Returns a random string to be used as a session ID
    }
}));

Take a look now at the implementation of a simple authentication flow.

app.post('/login', async (req, res) => {
    try {
        let user = await db.users.findOne({email: req.body.email});
        if(user !== null) {
            req.session.user = {
                  email: user.email,
                  name: user.name
            };
            res.redirect('/account');
        } else {
           // Login error
        }
    } catch(err) {
        res.sendStatus(500);
    }
});

When a user successfully logs in, we store his credentials in the session object. This object is shared among all routes and we can pass it to views.

app.get('/account', (req, res) => {
    if(!req.session.user) {
        res.redirect('/login');
    } else {
        res.render('account', {user: req.session.user});
    }
});

Here if the reference is not present in our session object, it simply means that our visitors are not logged in.

To remove a session variable, we can use the delete operator.

app.get('/logout', (req, res) => {
    if(req.session.user) {
        delete req.session.user;
        res.redirect('/login');
    } else {
        res.redirect('/');
    }        
});

It's clear now that in its essence session management is simply a matter of getting/setting/deleting a JavaScript object's properties.

Differences with PHP

As we said earlier, in ExpressJS sessions are created at application level. This means that when you launch your app, you're creating a brand new session handler for the whole Node process. Instead, in PHP sessions are created by request. When you hit a page which has session_start() in it, PHP checks whether the browser has already stored the session token. If so, it continues with the current session, otherwise it starts a new session.

Suppose now that you're implementing a shopping cart in Express. If you set the cart's variable at the very beginning, you'll simply get the unwanted result of having a single shopping cart shared among all the users of your website. In other words, session variables must be set locally after certain user's actions.

Prev Articles Next