menu

Questions & Answers

Persistent sessions with connect-session-sequelize

I am making a website with a login system and I would like the users to be able to stay logged in even after the browser has been closed. Only destroy the session when the user logs out. I have searched online for the solution and came across with the suggestion to use connect-session-sequelize . I read the documentation and put my best effort to make the code work but my lack of experience in this gets in a way.

Problem:

My code does not give me the result of keeping a user logged in after the server restart. My code is:

var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
var SequelizeStore = require('connect-session-sequelize')(session.Store);

var pug = require('pug');
var bodyParser = require('body-parser');
var bcrypt = require('bcrypt');

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static('public'));
app.use(cookieParser());

app.set('views', './views');
app.set('view engine', 'pug');

var Sequelize = require('sequelize');
var db = new Sequelize('postgres://'+ process.env.POSTGRES_USER + ':' + 
process.env.POSTGRES_PASSWORD + '@localhost/terranova', {
    host: 'localhost',
    dialect: 'postgres',
    storage: './session.postgres', 
    define: {
      timestamps: true
    }
});

var sessionStore = new SequelizeStore({
    db: db,
    checkExpirationInterval: 15 * 60 * 1000,
    expiration: 24 * 60 * 60 * 60 * 1000 
});

app.use(session({
  secret: 'salajhgdusdajss',
  store: sessionStore,
  resave: false,
  saveUninitialized: false,
  proxy: true
}));

sessionStore.sync()

var Session = db.define('Session', {
    sid: {
      type: Sequelize.STRING,
      primaryKey: true
    },
    userId: Sequelize.STRING,
    expires: Sequelize.DATE,
    data: Sequelize.STRING(50000)
});

var User = db.define('user', {
  username: Sequelize.STRING,
  password: Sequelize.STRING,
});

function extendDefaultFields(defaults, session) {
  return {
    data: defaults.data,
    expires: defaults.expires,
    userId: session.userId
  };
}

var store = new SequelizeStore({ 
   db: db,
   table: 'Session',
   extendDefaultFields: extendDefaultFields
});

Subproblems:

  1. The documentation indicates to add 'var store = new SessionStore' instead of 'var store = new SequelizeStore' but it gives me an error: 'SessionStore is not defined'. Not sure if I'm doing something wrong?

  2. I can see inside 'users' table, but for some reason, I cannot look inside the table of 'Sessions', with 'select * from Sessions;' I get the response of 'relation "sessions" does not exist'. Why is this so? enter image description here

  3. expiration: 24 * 60 * 60 * 1000 --> default expiry of 24 hours. Does this indicate the time of the session? If yes, what would be the maximum possible time (in case unlimited is impossible)?

Could someone please explain me what do I need to do/add/remove from my code to be able to achieve my goal?

For more info, here is the login page...

app.get('/login', function(req,res) {
    res.render('login')
})

app.post('/login', function(req,res) {
    var username = req.body.username
    var password = req.body.password

    User.findOne({
        where: {
            username: username
        }
    }).then(function(user) {
        if(username.length === 0 || password.length === 0) {
             res.render('login', {
                message: "Username or password missing"
            });
            return;
        };
        if(user == null) {
            res.render('login', {
                message: "User not in the system, please register"
            }); 
            return;
        } else {
            var hash = user.password
            bcrypt.compare(password, hash, function(err, result) {
                if (err) {
                    res.render('login', {
                        message: 'Invalid email or password, please try again or register'
                    })
                };
                if(result === true) {
                    req.session.user = user;
                    res.redirect('/home');
                }
                else {
                    res.render('login', {
                        message: "Something went wrong, please try again"
                     });
                };
            });
        };
    });
})

...and here is the home page.

app.get('/home', function(req,res) {
    var user = req.session.user

    if (user === undefined) {
        res.render('login', {
            message: 'Please log in to have the access'
        });
    } else {
        res.render('home', {
            user: user
        });
    }
})

Big thanks in advance for helping me!

Comments:
2023-01-11 09:20:44
1. I think SequelizeStore is okay for you. 2. Try to refer to it as "Session" in double quotes (Postgres is weird with cases). 3. Expiration can be as long as you want it to be!
2023-01-11 09:20:44
Thanks Dylan! I dived into the docum. again and it indicates that extendDefaultFields is optional, so I removed this. I still cannot access Sessions table even after adding double quotes, but the table gets added even without db.define("Session"), I think it's added with the session store connect-session-sequelize?
2023-01-11 09:20:44
I added expire: new Date(Date.now() + (30 * 86400 * 1000)) to app.use(session) and I can see in my terminal now when I log in: UPDATE "Sessions" SET "expires"='2017-10-10 10:02:52.487 +00:00'," Whenever I do something on the website, the session expire date gets renewed, so I think this should give me the result I need (only ends the session if the user is inactive for 2 months which is fine).
2023-01-11 09:20:44
Were you able to solve your problem? If so, would you consider updating the original post with the solution you've found so other can benefit from the knowledge?
Answers(0) :