How to use passport with express and socket.io? How to use passport with express and socket.io? express express

How to use passport with express and socket.io?


Here is a solution using Socket.IO 1.0 and Express 4.0. It is similar in spirit to Patrick's answer. The trick is that since Socket.IO 1.0 has a new middleware API, we can wrap Express's middleware and put it into the Socket.IO pipeline without delving into the low-level implementation of the session stores.

// Set up the Session middleware using a MongoDB session storeexpressSession = require("express-session");var sessionMiddleware = expressSession({    name: "COOKIE_NAME_HERE",    secret: "COOKIE_SECRET_HERE",    store: new (require("connect-mongo")(expressSession))({        url: "mongodb://localhost/DATABASE_NAME_HERE"    })});// Set up the Express servervar app = require("express")()    .use(sessionMiddleware)    .use(passport.initialize())    .use(passport.session())    // ... more middleware ...    .listen(8000);// Set up the Socket.IO servervar io = require("socket.io")(app)    .use(function(socket, next){        // Wrap the express middleware        sessionMiddleware(socket.request, {}, next);    })    .on("connection", function(socket){        var userId = socket.request.session.passport.user;        console.log("Your User ID is", userId);    });

The variable sessionMiddleware is a function that is designed to fit directly into the Express pipeline. It takes exactly three arguments: the request object, the response object, and a callback.

Socket.IO's pipeline expects its middleware to take only two arguments, however: the socket object (which contains the request object at socket.request) and a callback. Luckily sessionMiddleware does not require the response object to read the session from the store, so we simply pass it an empty object as the second argument.

Note that some comments below observe that this code renders the session read-only. This is the functionality we lose by not having a proper response object with Socket.IO.

In the above example I use a MongoDB session store (connect-mongo). You can use whatever session store fits your liking. Refer to the Connect wiki for a list of session stores.


I got it to work. What I had to to is get access to the sessionStore. Here is the code in case anyone else stumbles over this particular problem:

// # app.jsvar express     = require('express'),    routes      = require('./routes'),    http        = require('http'),    path        = require('path'),    app         = express(),    passport    = require('passport'),    SessionMongoose = require("session-mongoose"),    mongooseSessionStore = new SessionMongoose({        url: "mongodb://localhost/login",        interval: 120000     });var config       = require('game/config.js'), // holds my whole server configuration    server       = require('game/lib/server.js');// save sessionStore to config for later accessconfig.setSessionStore(mongooseSessionStore);// configure express to use passport and mongooseSessionStoreapp.configure(function(){    app.set('port', config.port);    app.set('env', config.environment);    app.set('dbPrefix', config.dbPrefix);    app.set('views', __dirname + '/views');    app.set('view engine', 'jade');    app.use(express.favicon());    app.use(express.bodyParser());    app.use(express.cookieParser());    app.use(express.session({secret : 'totallysecret', store : mongooseSessionStore })),    app.use(express.methodOverride());    app.use(passport.initialize());    app.use(passport.session());        app.use(app.router);    app.use(express['static'](path.join(__dirname, 'public')));});app.get('/', routes.index);app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));app.get('/auth/facebook/callback',     passport.authenticate('facebook', { successRedirect: '/',                                        failureRedirect: '/' })); // #### Init httpservervar httpServer = http.createServer(app);httpServer.listen(app.get('port'));// #### Server startupserver.init(httpServer);

My serialization functions look simple like this:

passport.serializeUser(function(user, done) {    // saves user.email to session.passport.user    done(null, user.email);});passport.deserializeUser(function(obj, done) {    done(null, obj);});

And finally the socket.io implementation:

var util              = require('util'),    connect           = require('connect'),    parseSignedCookie = connect.utils.parseSignedCookie,    cookie            = require('express/node_modules/cookie'),    io                = require('socket.io').listen(httpServer);var config = require('../config.js');  io.configure(function () {    io.set('authorization', function (data, callback) {        if(data.headers.cookie) {            // save parsedSessionId to handshakeData            data.cookie = cookie.parse(data.headers.cookie);            data.sessionId = parseSignedCookie(data.cookie['connect.sid'], 'totallysecret');        }        callback(null, true);    });    io.on('connection', function(socket) {        // reference to my initialized sessionStore in app.js        var sessionStore = config.sessionStore;        var sessionId    = socket.handshake.sessionId;        sessionStore.get(sessionId, function(err, session) {            if( ! err) {                if(session.passport.user) {                    console.log('This is the users email address %s', session.passport.user);            }        });    });});

Using the session-mongoose module I have access to:

sessionStore.get(sessionId, callback)sessionStore.set(sessionId, data, callback) sessionStore.destroy(sessionId, callback) sessionStore.all(callback)    // returns all available sessionssessionStore.clear(callback)  // deletes all session datasessionStore.length(callback) // returns number of sessions in the 


You can make use of express-socket.io-session. You can get the passport session user with socket.handshake.session.passport.user . It supports both reading and writing to the session store.

NB: Works with express > 4.0.0 and socket.io > 1.0.0 and won't be backward compatible