Skip to main content

How to creating and managing sessions in Node.js and Express.js for Beginners

In this article, I am going to Creating and managing sessions in in Node.js. We will use express as a framework and various other modules such as body-parser to handle form data.

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.

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.

Comments

Popular posts from this blog

4 Ways to Communicate Across Browser Tabs in Realtime

1. Local Storage Events You might have already used LocalStorage, which is accessible across Tabs within the same application origin. But do you know that it also supports events? You can use this feature to communicate across Browser Tabs, where other Tabs will receive the event once the storage is updated. For example, let’s say in one Tab, we execute the following JavaScript code. window.localStorage.setItem("loggedIn", "true"); The other Tabs which listen to the event will receive it, as shown below. window.addEventListener('storage', (event) => { if (event.storageArea != localStorage) return; if (event.key === 'loggedIn') { // Do something with event.newValue } }); 2. Broadcast Channel API The Broadcast Channel API allows communication between Tabs, Windows, Frames, Iframes, and  Web Workers . One Tab can create and post to a channel as follows. const channel = new BroadcastChannel('app-data'); channel.postMessage(data); And oth...

Certbot SSL configuration in ubuntu

  Introduction Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free  TLS/SSL certificates , thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot, that attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx. In this tutorial, you will use Certbot to obtain a free SSL certificate for Apache on Ubuntu 18.04 and set up your certificate to renew automatically. This tutorial will use a separate Apache virtual host file instead of the default configuration file.  We recommend  creating new Apache virtual host files for each domain because it helps to avoid common mistakes and maintains the default files as a fallback configuration. Prerequisites To follow this tutorial, you will need: One Ubuntu 18.04 server set up by following this  initial ...

Working with Node.js streams

  Introduction Streams are one of the major features that most Node.js applications rely on, especially when handling HTTP requests, reading/writing files, and making socket communications. Streams are very predictable since we can always expect data, error, and end events when using streams. This article will teach Node developers how to use streams to efficiently handle large amounts of data. This is a typical real-world challenge faced by Node developers when they have to deal with a large data source, and it may not be feasible to process this data all at once. This article will cover the following topics: Types of streams When to adopt Node.js streams Batching Composing streams in Node.js Transforming data with transform streams Piping streams Error handling Node.js streams Types of streams The following are four main types of streams in Node.js: Readable streams: The readable stream is responsible for reading data from a source file Writable streams: The writable stream is re...