Updating cookie session in express not registering with browser

Casper picture Casper · Oct 26, 2012 · Viewed 7.3k times · Source

I've set up a working login test as follows:

var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var routes = require('./routes/index.coffee');
var passport = require('passport');

var LocalStrategy = require('passport-local').Strategy;
var User = require('./userdb.coffee');
var app = express();
var RedisStore = require('connect-redis')(express);

passport.use(new LocalStrategy(function(username, password, done) {
  return User.findOne({
    username: username
  }, function(err, user) {
    if (err) {
      return done(null, false, message: error);
    }
    if (!user) {
      return done(null, false, {
        message: 'Unknown user'
      });
    }
    if (!user.validPassword(password)) {
      return done(null, false, {
        message: 'Invalid password'
      });
    } else {
      return done(null, user);
    }
  });
}));

passport.serializeUser(function(user, done) {
  return done(null, user);
});

passport.deserializeUser(function(user, done) {
  return done(null, user);
});

app.configure(function() {
  app.set('port', process.env.PORT || 5003);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.enable('trust proxy');
  app.use(express["static"](path.join(__dirname, 'public')));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('SOMESECRET'));
  app.use(express.session({
    cookie: {
      maxAge: 10 * 60 * 1000
    },
    key: 'express.sid',
    secret: 'SOMESECRET',
    store: new RedisStore({
      port: 6379,
      host: 'localhost'
    })
  }));
  app.use(passport.initialize());
  app.use(passport.session());
  return app.use(app.router);
});

var check_auth = function(req, res, next) {
  if (req.isAuthenticated()) {
    console.log(req.session.cookie.expires);
    return next();
  }
  return res.redirect('/login');
};

app.get('/', check_auth, routes.index);
app.get('/login', routes.login);
app.get('/logout', routes.logout);
app.post('/authenticate', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/login'
}));

app.listen(app.get('port'), '0.0.0.0');

The routes and User logic is omitted, as I take it they're irrelevant to my issue, but I'll happily share them if needed (they're very small, this is just to get a small proof of concept up and running).

Login works, reading the session works, rendering templates based on session values work. My problem is with maxAge/expires. I'm not sure where-in the problem lies, but I'll try to describe it:

When I log in, the session is saves with passport.js, stored correctly in my RedisStore, and a cookie pointing at the session is returned to the browser. On subsequent requests the cookie is successfully found and points to the correct session from my SessionStore. req.session.cookie show an UPDATED expires and in my redis server, the TTL is reset to 10 minutes (600).

My problem is that the cookie remains at the same expirary in the browser (Chrome, windows and Mac).

So my question is: How can I debug this further? As req.session is updated (by express, passport and connect-redis internally/automatically), I'm wondering where the problem lies, and what I should do to fix this: Cookie remains at the initial maxAges/expires.

Any tips, pointers or ideas are grately appreciated.

Answer

aap picture aap · Dec 22, 2014

Express-session supports a rolling cookie expiration date. Unfortunately, it was only recently documented.

Use the "rolling" option for your session. This "forces a cookie set on every response" and "resets the expiration date." You want to set rolling to true.

Also pay attention to the "resave" option. That "forces session to be saved even when unmodified..." You'll likely want to set that option to true as well. Note that even though the default value is true for this option, you should set the value explicitly. Relying on the default for this option, rather than setting it explicitly, is now deprecated.

Try something like:

app.use( session( { secret: 'keyboard cat',
                    cookie: { maxAge: 60000 },
                    rolling: true,
                    resave: true, 
                    saveUninitialized: false
                  }
         )
);

Here's the documentation. Look under "Options" and "options.resave": https://github.com/expressjs/session .