how to manage session using Node and express

How to Manage Session using Node.js and Express

Session handling in any web application is very important and is a must-have feature, without it, we won’t be able to track user and it’s activity.

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

YOUTUBE DEMO DOWNLOAD

At the time of writing article, the latest version of Express is 4.16.4.

What we are buiding

To demonstrate Session handling in Node, I have developed a basic Log-in and log-out System. In this User can log-in by providing their email, and that email will be used for further Session tracking. Once User log-out, Session will be destroyed and User will be redirected to the home page.

Creating Node Project

Let’s create a new Node project. Create a new folder and switch to it using the terminal.

Run this command to create a new Node project.

npm init --y

This command will create a new package.json file. Let’s install the required dependency.

npm install --save express express-session body-parser

Once the dependencies are installed, we can proceed to code our app.

If you are new to Node and Express then you won’t regret taking our Node course. Its FREE!

How to use Express Session ?

Before heading to actual code, i want to put few words about express-session module. to use this module, you must have to include express in your project. Like for all packages, we have to first include it.

server.js
const express = require('express');
const session = require('express-session');
const app = express();

After this, we have to initialize the session and we can do this by using following.

app.use(session({secret: 'ssshhhhh'}));

Here ‘secret‘ is used for cookie handling etc but we have to put some secret for managing Session in Express.

Now using ‘request‘ variable you can assign session to any variable. Just like we do in PHP using $_SESSION variable. for e.g

var sess;
app.get('/',function(req,res){
    sess=req.session;
    /*
    * Here we have assign the 'session' to 'sess'.
    * Now we can create any number of session variable we want.
    * in PHP we do as $_SESSION['var name'].
    * Here we do like this.
    */

    sess.email; // equivalent to $_SESSION['email'] in PHP.
    sess.username; // equivalent to $_SESSION['username'] in PHP.
});

After creating Session variables like sess.email , we can check whether this variable is set or not in other routers and can track the Session easily.

Tracking session in global variable won’t work with multiple users. This is just for the demonstration.

Project Structure

We are going to put all of Server side code in the server.js file. Front-end code will be placed inside the views folder.
session directory

Here is our Server side code.

server.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const router = express.Router();
const app = express();

app.use(session({secret: 'ssshhhhh',saveUninitialized: true,resave: true}));
app.use(bodyParser.json());      
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname + '/views'));

var sess; // global session, NOT recommended

router.get('/',(req,res) => {
    sess = req.session;
    if(sess.email) {
        return res.redirect('/admin');
    }
    res.sendFile('index.html');
});

router.post('/login',(req,res) => {
    sess = req.session;
    sess.email = req.body.email;
    res.end('done');
});

router.get('/admin',(req,res) => {
    sess = req.session;
    if(sess.email) {
        res.write(`<h1>Hello ${sess.email} </h1><br>`);
        res.end('<a href='+'/logout'+'>Logout</a>');
    }
    else {
        res.write('<h1>Please login first.</h1>');
        res.end('<a href='+'/'+'>Login</a>');
    }
});

router.get('/logout',(req,res) => {
    req.session.destroy((err) => {
        if(err) {
            return console.log(err);
        }
        res.redirect('/');
    });

});

app.use('/', router);

app.listen(process.env.PORT || 3000,() => {
    console.log(`App Started on PORT ${process.env.PORT || 3000}`);
});

In the code shown above, there are four routers. First, which render the home page, the second router is used for login operation. We are not doing any authentication here for the sake of simplicity.

The third router is used for admin area where the user can only go if he/she is log-in. The fourth and the last router is for session destruction.

Each router checks whether the sess.emailvariable is set or not and that could be set only by logging in through front-end. Here is my HTML code which resides in views directory.

views/index.html
<html>
<head>
<title>Session Management in NodeJS using Node and Express</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
    var email,pass;
    $("#submit").click(function(){
        email=$("#email").val();
        pass=$("#password").val();
        /*
        * Perform some validation here.
        */
        $.post("/login",{email:email,pass:pass},function(data){
            if(data==='done') {
                window.location.href="/admin";
            }
        });
    });
});
</script>
</head>
<body>
<input type="text" size="40" placeholder="Type your email" id="email"><br />
<input type="password" size="40" placeholder="Type your password" id="password"><br />
<input type="button" value="Submit" id="submit">
</body>
</html>

In jQuery code, we are calling our Router ‘/login’ and redirecting it to the ‘admin‘ if log-in is successful, you can add validation to fields as per your requirement, for demo purpose i have not added any.

The Bug Alert!

As I have mentioned earlier, using a global variable for the session won’t work for multiple users. You will receive the same session information for all of the users.

So how do we solve this? By using a session store.

We save every session in the store so that one session will belong to the one user only. I have explained and build session store using Redis in this article.

For the quick reference, he is how we can extend the code shown above using Redis as a session store.

First, you need to install Redis on your computer. Click here to learn how to install Redis.

Then, install these dependencies in your project.

npm i --S redis connect-redis

Here is the codebase after upgrading it to support Redis.

server.js
/*
 * Manage Session in Node.js and ExpressJS
 * Author : Shahid Shaikh
 * Version : 0.0.2
*/

const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const redis = require('redis');
const redisStore = require('connect-redis')(session);
const client  = redis.createClient();
const router = express.Router();
const app = express();

app.use(session({
    secret: 'ssshhhhh',
    // create new redis store.
    store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 260}),
    saveUninitialized: false,
    resave: false
}));

app.use(bodyParser.json());      
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname + '/views'));

router.get('/',(req,res) => {
    let sess = req.session;
    if(sess.email) {
        return res.redirect('/admin');
    }
    res.sendFile('index.html');
});

router.post('/login',(req,res) => {
    req.session.email = req.body.email;
    res.end('done');
});

router.get('/admin',(req,res) => {
    if(req.session.email) {
        res.write(`<h1>Hello ${req.session.email} </h1><br>`);
        res.end('<a href='+'/logout'+'>Logout</a>');
    }
    else {
        res.write('<h1>Please login first.</h1>');
        res.end('<a href='+'/'+'>Login</a>');
    }
});

router.get('/logout',(req,res) => {
    req.session.destroy((err) => {
        if(err) {
            return console.log(err);
        }
        res.redirect('/');
    });

});

app.use('/', router);

app.listen(process.env.PORT || 3000,() => {
    console.log(`App Started on PORT ${process.env.PORT || 3000}`);
});

If you notice in the code shown above, we have removed the global variable. We are using Redis to store our session instead. Try this multiple users and you should see unique session for each user.

I highly recommend following this article for more detailed information.

How to run example code

Download code and extract the zip file. Open your command prompt or Terminal and switch to the directory. Install dependency first by using.

npm install

Then run code using

node server.js

Visit localhost:3000 to view the app.

Session Using Node and Redis

Conclusion:

Like I mentioned session is very important for any web application. Node.js allows us to create an HTTP server and HTTP is a stateless protocol. It stores no information about previous visit and Express solves this problem very beautifully.

Further reading

Nodejs tutorials
Node.js MySQL Tutorial
Programming a Voice Controlled Drone Using Node and ARDrone

Shahid

Founder of Codeforgeek. Technologist. Published Author. Engineer. Content Creator. Teaching Everything I learn!

Related Posts

85 Comments

  1. Hi man !
    Thanks for this great post ! I’ve got an issue with session managing, if you got some minuts could you help me please ?
    I written some routes with app.get(). I’ve done an app.post for the login, and the mechanism works well (I’m going to auth my user by searching into a mongodb database). I then store his username in sess.username.
    But when the user then navigate to the other routes, and I check sess.username it’s always null.

    I’ve written sess = req.session; in the top of every routes dedicated code and then I checked the sess.username.

    Oh, and sess is a global variable.
    Do you see what is messing up ? Thanks in advance 🙂

    1. Hi Alex,
      Thanks for your posting your question.
      Programmatically your approach is correct. Before i put my comment on it, could you please verify that your app.use(session(–rest params–)) uses this resave: true.
      Thanks.

      1. Thanks for replying Shahid 🙂
        This value is true by default but I tried anyway to affect true to the resave option in session. I also tried to do a session.save function at login.
        Maybe in the new version of express-session it is impossible to bind a value to the session objet ? thus i didn’t noticed something like this into the express-session doc …

        1. I am facing the same problem.Did u got any solution ?/
          have u tried changing app.use(session.-) i.i another version of session? Plz let me know!!

    2. Alex, I realize this was a while back, but I’ll reply in hopes that it resolves someone stuck on a similiar problem. The reason your global variable sess is null is because its being reassigned for each request after it was initially set. The purpose of binding the session to the req variable is because its the only response-specific state being passed between the express middleware and routing.

      1. Well, facing the same problem I think I got a solution : it seems like sess variable must be assigned to req.session in an other route before filling it via login route. Typically via the route( ‘/’ )

  2. Nice Tut! Is there a better way to make {email, password, phone} more dynamic and match up destination structure?

    Thanks!

    1. To handle concurrent session , you need to create unique Session ID and give it to client once the session is set so that next time until they logout / close browser they need to pass that unique ID in every request they made to server and you need to check it in every router.

      1. Thanks for the reply.
        Actually what i mean to ask was, can 2 treads simultaneously access session object and corrupt it’s state ? and how to prevent that.

        I’m coming from servlet background, where session object is shared, so we synchronize it’s access.

      2. Hi Shahid,
        I am implementing the session handling for the first time. I am using NodeJs & express and Extjs for server and client side implementation respectively. The above reply of yours help me a lot. Thanks for that! However, I am struggling to send the sessionID fro client (ExtJs) back to server. Can you suggest me a way to do this? Also, if i am able to send that session ID somehow, What should i compare it with? req.sessionID?

        1. If you want to send Anything to Nodejs server, you can do it using GET or POST HTTP method. Now as per your concern i am not sure why you want to send Session ID which you got from back-end to front-end again ?

          1. Even I thought it was not needed to send the ID back to server and implemented it that way. But this reply of yours to “Arjun’s” query some days back, confused me slightly.

            “To handle concurrent session , you need to create unique Session ID and give it to client once the session is set so that next time until they logout / close browser they need to pass that unique ID in every request they made to server and you need to check it in every router”

            I am sorry if I asked something very obvious but as i have told u I am implementing this for the first time and so i want to make sure concurrent sessions are handled.

  3. Hello!

    How do I get to make this work with authFactory? Can’t seem to get any value for sess.email. It says it is undefined

    app.get(‘/api/auth/login/session’,function(req,res){
    sess = req.session;
    if(sess.email)
    {
    console.log(sess.personid);
    /*
    results.personid = req.body.personid;
    results.name = req.body..firstname;
    results.email = req.body..email;
    */

    }
    else
    {
    console.log(‘sess email is undefined’);
    }
    });

      1. Hey Shahid, I see where my problem is! I am not using php but express.js as my api. I am all new with angular but your tuts are amazing. I actually am doing a freelance project just from stuff I learned from you!

        Thanks!!

          1. Hello Shahid

            I am using purely js for my api (express) but when user tries to login user gets kicked out.

            //app.js
             .run(function ($rootScope, $location, authFactory) {
                $rootScope.$on("$routeChangeStart", function (event, next, current) {
                    $rootScope.authenticated = false;
                    authFactory.GetSession('session').then(function (results) {
                        if (results.personid) {
                            $rootScope.authenticated = true;
                            $rootScope.personid = results.personid;
                            $rootScope.name = results.firstname;
                            $rootScope.email = results.email;
                        } else {
                            var nextUrl = next.$$route.originalPath;
                            if (nextUrl == '/signup' || nextUrl == '/login') {

                            } else {
                                $location.path("/login");
                            }
                        }
                    });
                });
            });
            //serviceFactory
            app.factory('authFactory', ['$http', function($http) {

                //var urlBase = 'http://localhost:8001/api/auth/';
                var urlBase = 'http://localhost:8001/api/auth/';
                var authFactory = {};

                authFactory.LogIn= function () {
                return $http.post('http://localhost:8001/api/auth/login');
                };

                authFactory.LogOut= function (q) {
                return $http.get('http://localhost:8001/api/auth/logout');
                }; 

                authFactory.GetSession = function (q) {
                    return $http.post('http://localhost:8001/api/auth/login/session/');
                };

               
                authFactory.Signup = function (q) {
                    return $http.post(urlBase + q);
                };

               authFactory.get = function (q) {
                    return $http.get(urlBase + q).then(function (results) {
                        return results.data;
                    });
                };

                return authFactory;
            }]);

            //api.js
            app.post('/api/auth/login', function(req, res){
                sess=req.session;
               
                var email = req.body.email;
                var password = req.body.password;
               
                //In this we are assigning email to sess.email variable.
                //email comes from HTML page.
                sess.email = email;
                sess.password = password;
               
                connection.query('SELECT * FROM persons where email = "' + email + '" and password = "' + password + '"', req.params.id, function(err, rows, fields) {
                    if (err) {
                        console.error(err);
                        res.statusCode = 500;
                        res.send({
                            result: 'error',
                            err:    err.code
                        });
                    }
                    res.send(rows);
                });  
             
            });
    1. Every user who connect with your HTTP server gets a connection thread and Session is maintained for that thread. If you have code to demonstrate that its wrong then it would be awesome.

  4. How will your setup work among multiple node applications? I’m assuming since you haven’t configured any shared storage (such as Redis or similar) for your session, that the default memory store is used. If that’s the case – and requests are handled by different applications (running on different processes) or perhaps (if on AWS) by different EC2 instances – then none of the above will work.

    1. Yeah you are right. Above code was for handling session in simple web application. For shared instance we need storage like Redis or something to store session key. Will write tutorial on that. Thanks.

  5. Hi, Thanks for the great tutorial but I am facing an error. I am using express 4.0 and implementing session in routes/index.js

    In the post when I do,
    sess=req.session;
    sess.usr=req.body.username;

    I get error as – Cannot set property ‘usr’ of undefined

    I have also tried doing –
    var sess={usr:1,
    st:2};

    Still no luck.

    Kindly help me.

  6. HI ,

    Nice tutorial !
    Can you please update to manage more then one user login at the same time .When ever a new request comes the old session data is replace by the new request .
    code example
    app.post(‘/validate’,function(req,res){
    sess=req.session;
    sess.username=req.body.username});

    by the req.body.username i getting the username.

  7. hello,

    Thanks for sharing administration with Node.js and expressjs sessiones

    I have a question

    It has the following
    app.get(‘/logout’,function(req,res){
    req.session.destroy(function(err){
    if(err)console.log(err);
    res.redirect(‘/’);
    }
    });

    After removing the session is redirected to the root

    After being at the root , if I make a back in the browser displays the previous page which should not happen

    You know that makes this behavior?

    What would be the solution?

    I appreciate your time

    note :
    Before running app.get , I have a middleware where only verified if there is a session I make a next () ;
    otherwise I make a redirect to the root

    1. Hi,

      Previous page is also the Router and if you are doing validation of session in each router or in Middle ware then this should not happen.

      If session is inactive then redirect to home ( / ).

      Mail me code if you can.

      Thanks,
      Shahid.

    2. I’m facing a similar problem. Were you able to find a solution? If you did, could you please email it to me as well

  8. Hi Shahid,

    I have implemented passportjs for user authentication and authorization , I want to get the user details stored in session in angularjs(html not jade) frontend ?I don know how to move further Could you pls help me out ? I can see the browser cookie having the session userid but im not able to print the session details in index.js where I do my routing

    module.exports = function(passport){
    router.get(‘/’, isAuthenticated, function(req, res){

    var user = req.session.user;
    var a = req.user.username;
    var b = req.user.password;
    var c = req.user.emailid;
    console.log(a); // not printing in the console
    console.log(b); // not printing in the console
    console.log(c); // not printing in the console

    res.render(‘home’, { title: ‘User session Home’, user: req.user });

    });

  9. Shahid,
    I added the below 2 lines in app.js
    app.set(‘view engine’, ‘html’);
    app.engine(‘html’, ejs.renderFile);

    and tried fetching the json in html but cudn… Can you show a sample of how to get json in html ?
    (OR) do i convert the .html into .ejs ?

  10. Hi Shahid ,

    I got the express session username in html without templating engine 🙂 Thank you so much for suggesting ejs. Now my issue is when i click logout btn the passport/express session isnt destroyed ,redirection to home doesn work and i also want to remove the username from the html.. im quite unclear abt logout routing whether im doing the right way or not . Your emailID pls !!

  11. hi man.

    i am from south korea.

    i read well your tutorial and it helped me a lot. (sorry i do not english well)

    can i ask one question?

    long time ago, i read a article for session, in the article, ‘cookie-parser’ was necessary to use session. look following example code.

    [psedo code]
    app.use(cookieParser(~~~)); // cookieparser is located before session for working always.
    app.use(session(~~~));

    but in your tutorial, you didn’t use cookie-parser.

    express or express session is changed about session mechanism?

  12. hey Shahid !!

    m trying to render a web page designed in polymer but unfortunately its is unable to inherit any of its data from polymer script if use normal express server . But i tried to do that with python it works good on that, can you please help me out to sort this issue. How can i run a normal polymer designed static page on Node sever other wise how to use Http server (in python : python -m http.server)

        1. I know that very well but its programmer who made that stack and session has to be always controlled by Server not UI.

          You need to view this tutorial to understand the working example.

  13. Override the session value.
    var express = require(‘express’);
    var session = require(‘express-session’);
    var sess;

    step:1

    router.post(“/login”, function(req, res) {
    var email = “[email protected]”;
    sess = req.session;
    sess.email = email;
    res.send({
    data : sess
    });
    });

    step:2
    router.post(“/update”, function(req, res) {
    var email = “[email protected]”;
    sess = req.session;
    sess.email = reqData.email;
    res.send({
    data : sess
    });
    });

    step:3

    router.get(“/check”, function(req, res) {
    sess = req.session;
    var email = sess.email;
    console.log(email);
    //Here display first value.([email protected])
    //how can i get email value ([email protected])?
    });

    How can I override the session value?

  14. Hi shahid, I tried your tutorial, i have app.js as my main file. I want to write the rest of the code in another file in controllers. But when i try to run it, it gives me an error “cannot read property of undefined”. Please help me out

  15. Hi shahid,iam new to nodejs.I tried this tutorial it is working well but my problem is i made my own html page and i styled it with css,now i placed my stylesheet also in views folder and i gave that path in my html page but when i visit localhost:3000 only the plain html page is displaying,css is not supporting.so how can i display the page along with css.Please help me out.

  16. vn, how the fuck you supposed this should work?
    Like, author will leave all his tasks and start working on your problem? which is absolutely not relevant to this topic.
    are you retarded or what??

  17. thanks dude,its been amazing learning from you,I have finally learnt how to manage session using Node.js

    1. Please help in maintaining the same session id throughout the session for a single user.
      When I declared session id as global, same session id is retrieved for different users. How can this happen?
      How to solve the problem?

  18. Hey shahid first of all thanks for this amazing tutorial. My problem is when my browser close then my session expire i m using sess.cookie.maxAge = false ; but it’s not work Thanks In advance.

  19. Hi,

    If Node Server stops due to some mongodb error or else, then session expires/out, so the user click any other route, the page will redirect to login…how can i fix this ?

    Thanks

  20. Hi

    I have links:
    res.write(“Pear” + “Pear”);

    app.get(‘/addtocart/:pid’, function (req, res, next) {
    sess = req.session;
    if (sess.cart === undefined)
    sess.cart = [];
    var phoneId = req.params.pid;
    console.log(phoneId);
    //alert(phoneId);
    sess.cart.push(phoneId);
    console.log(“cart contains : “+sess.cart.length);
    next();
    //res.redirect(‘/products’);
    });

    this code adds to cart , but it redirects away
    how to stay on products page?

    regards
    and thanks for good tutorial

  21. Hi shahid,
    I have written code for login , user details are kept in session , while another function doesnot reflectinng complete session
    ///Here is login function
    exports.AdminLogin = function (req, res) {
    sess = req.session;
    sess.UserId = ‘someID’;
    sess.Email = ’email’;
    sess.isAuthenticated = true;

    }
    ///Another function here session UserId and email not reflecting
    exports.TimeSlotAdd = function (req, res) {
    sess = req.session;
    console.log(sess,’session’);
    }

    her in TimesSlot function i can get isAuthenticated but not UserID and Email

  22. I have this code:

    let session = null;
    app.use((req, res, next) => {
    session = req.session;
    if (session.username) {
    console.log(‘Has session username’);
    } else {
    console.log(‘Has no session username’);
    res.redirect(‘/auth/login’);
    }

    console.log(new Date() + ‘|’ + req.url);
    next();
    });

    routes.list(app); // list of routes, ex.: app.use(‘/’, homeController.index);

    I’m getting this error:

    _http_outgoing.js:356
    throw new Error(‘Can\’t set headers after they are sent.’);
    ^

    Error: Can’t set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
    at ServerResponse.header (/home/julez/Workspace/js/topzeluj/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/home/julez/Workspace/js/topzeluj/node_modules/express/lib/response.js:170:12)
    at done (/home/julez/Workspace/js/topzeluj/node_modules/express/lib/response.js:1004:10)
    at load (/home/julez/Workspace/js/topzeluj/node_modules/twig/twig.js:7713:18)
    at loadTemplateFn (/home/julez/Workspace/js/topzeluj/node_modules/twig/twig.js:5726:18)
    at tryToString (fs.js:457:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:444:12)

  23. Hello, i just want to tell you this is first explanation what i can understand easily and perfect.
    Thanks for awesome guide man!

  24. The below is my code snippet
    global.sess;
    app.get(‘/’,function(req,res){
    sess=req.session;
    if(sess.email){
    res.redirect(‘/admin’);
    }
    else{
    res.render(‘index.html’);
    }
    });

    app.post(‘/Test’,function(req,res){
    sess = req.session;
    //In this we are assigning email to sess.email variable.
    //email comes from HTML page.
    // sess.email={};
    sess.email=req.body.email;
    res.end(‘done’);
    });

    I am facing the error :
    TypeError: Cannot set property ’email’ of undefined

    Can you please help
    TIA

    1. Just replace the global.sess to var sess = null; and it should work fine.

      Also, I strongly suggest you do not use this code in production, this is just for an explanation purpose.

      In the production, you should use session store along with this code.

      Here is the tutorial for the same.

  25. Great Explanation. Really enjoyed the article reading. I suggest you to write more and more tutorials like these.

Leave a Reply to Miley Cyrus Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.