Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS cookies don't work with sessions in Express 4

I've updated my NodeJS application to Express 4.0 and now I can't set my own cookies in addition to the express-session cookie. This problem only happens on the first request of any session, when the user reloads the page the custom cookies are there.

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var session = require('express-session');

var app = express();

app.set('port', process.env.PORT || 3000);

app.use(express.static(path.join(__dirname, 'public')));
app.use(require('body-parser')());
app.use(require('method-override')());
app.use(require('cookie-parser')('cookie-secret'));
//app.use(session({ secret: 'secret', key: 'sid'})); //uncomment this to see the problem

app.get('/', function(req, res, next) {
    res.cookie('testing', 'test'); //this isn't set if using 'app.use(session...)'
    res.send('This is a cookie test');
});

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

To test: 1. Run the above code, the cookie "testing" is sent to the browser correct. 2. Then clear the cookies and uncomment the "app.use(session..." line. 3. Run the application and the only cookie is the "sid". Where's "testing"? 4. Reload the page (without clearing cookies) and the "testing" cookie is there.

It's essential that all of my cookies are there on the first request.

like image 587
nuckolhead Avatar asked Apr 19 '14 16:04

nuckolhead


2 Answers

This works for me:

var mw = {
  favicon: require('static-favicon'),
  logger: require('morgan'),
  bodyParser: require('body-parser'),
  cookieParser: require('cookie-parser'),
  session: require('express-session'),
  methodOverride: require('method-override')
};

var MongoStore = require('connect-mongo')(mw);
app.store = new MongoStore(...);


app.use(function(req, res, next) {
  if ('HEAD' === req.method || 'OPTIONS' === req.method) return next();
  var writeHead = res.writeHead;
  res.writeHead = function() {
    res.cookie('XSRF-TOKEN', req.session && req.session._csrfSecret);
    writeHead.apply(res, arguments);
  };
  next();
});

app.use(mw.session({
  key: 'yourCookieID',
  cookie: {
    maxAge: 3600000 * 24 * 7
  },
  store: app.store
}));
like image 190
malix Avatar answered Sep 25 '22 22:09

malix


In express-session you are attempting to use the key: option which was replaced with name: option. You will want to use the genid: option to set the sid, make sure it is unique(I suggest, uuid version 4). The express-session package will also handle your cookie management.

// Session create
var hour = 3600000;

app.use(session({
    genid: function(req) {
          return uuid.v4(); // This comes from the node-uuid package
    },
    secret: 'secret key',
    cookie: { secure:  true,
              expires: new Date(Date.now() + hour),
              maxAge:  hour },
    saveUninitialized: true,
    resave: true
}));

To access the session data:

req.session

To access the cookie data:

req.session.cookie
like image 37
Brandon Clark Avatar answered Sep 24 '22 22:09

Brandon Clark