Express 3.4.8 + Socket.io 0.9.16 sessions

I've been struggling a bit laterly about making express sessions working and available from socket.io opened connections.

I've found many methods described on the Internet but none of them were working in my case. I finally made it work by using the express-session module.

So, first thing to do is to install express-session (of course you need a functional Express server):

npm install express-session

Then, set express up to use express-session for session management.

var session  = require('express-session');

app.configure(function() {
	app.use(express.cookieParser(config.secret));
	app.use(session({
		key: 'express.sid',
		secret: config.secret,
		cookie: { 
        	httpOnly: false, 
            maxAge: 24*60*60*1000 
        }
    }));
});

Default configuration uses MemoryStore to keep session data, you need to create a sessionStore variable in order to be able to access the session data.

I choosed to use MongoDB because I need the session data to be kept when server is restarted and because I didn't want to keep too much data inside memory. However, you can simply use MemoryStore if you don't care.

First, npm install connect-mongo and then :

var session  = require('express-session');

var MongoStore = require('connect-mongo')(express);
var sessionStore = new MongoStore({
	host : 'localhost',
	db : 'myDbName',
	collection : 'session',
	stringify : false
});

app.configure(function() {
	app.use(express.cookieParser(config.secret));
	app.use(session({
		store: sessionStore,
		key: 'express.sid',
		secret: config.secret,
		cookie: { 
        	httpOnly: false, 
            maxAge: 24*60*60*1000 
        }
    }));
});

At this point, sessions should already be working and available inside express routes and session data should be stored inside the storage you chose.

The last thing to do is to make the session available from socket.io connections. This is done with the following function which adds the session to the socket.io handshake data.

io.set('authorization', function (handshakeData, accept) {
  if (handshakeData.headers.cookie) {
    handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
    handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['express.sid'], config.secret);
    if (handshakeData.cookie['express.sid'] == handshakeData.sessionID) {
      return accept('Cookie is invalid.', false);
    }
  } else {
    return accept('No cookie transmitted.', false);
  }
  handshakeData.sessionStore = sessionStore;
  sessionStore.load(handshakeData.sessionID, function(err, sess){
    if (err || !sess) {
      accept('Error when creating session: '+err, false);
    } else {
      handshakeData.session = sess;
      accept(null, true);
    }
  });
});

Finally, your session data should be available inside your socket.io callbacks by using socket.handshake.session. You may need to keep the session fresh whenever a socket is opened, if so, simply do this to touch (refresh) session every minute :

io.sockets.on('connection', function (socket, pseudo) {
  var hs = socket.handshake;

  var intervalID = setInterval(function () {
    hs.session.reload( function () {
      hs.session.touch().save();
    });
  }, 60 * 1000);
  socket.on('disconnect', function() {
    clearInterval(intervalID);
  });
});

The code I give here is only small excerpt from a larger project I'm working on so I didn't really test it, let me know if I forgot anything or if you know a better way to make everything work. Thank you for reading.