Question

I'm writing a NodeJS solution which relies on Passport for authorisation and SocketIO.

When a socket connection is accessed I want to be able to fetch the users session/profile which is stored in MongoDB if there is one. (Through connect-mongo).

I have implemented Passport.socketio to access this from the Store.

io.set('authorization', passportSocketIo.authorize({
        passport: require('passport'),
        cookieParser: cookieParser,
        key:         'connect.sid',       
        secret:      'StackSecret',
        store:       new store({
            db: mongoose.connection.db,
            collection: 'sessions',
        }),

        fail:        FailedMethod
    }));

I can then access the user's profile from "socket.handshake.user"..

socket.on("callback", function(){
     console.log(socket.handshake.user); //Fetch Logged in user's Id
})

This would work perfectly if I was trying to block access to the socket but I want it to be open to every connection (Both with a session or not). I just want to be able to access their Passport session Id if they are logged in.

What is my best way of accessing a sessions userId from SocketIo?

I'm hoping Passport.socketio is overkill and I can do it easily without it.

Was it helpful?

Solution 2

I like the fact that posting a question often helps you answer it!

The fail Method takes 4 parameters data, message, error, callback.

You can fire the call back with a success true and it will continue without authorisation.

function onAuthorizeFail(data, message, error, accept){
    accept(null, true);
};

OTHER TIPS

Your own answer would probably suffice for this case, but you answered a more general question (how to access session info for a socket connection). The following is how I do it generally. Additionally, I normally register all the routes in such a way that they get a reference to a config, so I can also provide every request handler with a socket connection specific to this particular session:

var cookie = require("cookie"),
    parseSignedCookie = require('connect').utils.parseSignedCookie;

var io = require('socket.io').listen(httpServer);
io.sockets.on("connection", function(socket) {
    if (socket.handshake.headers.cookie) {
        var cks = cookie.parse(socket.handshake.headers.cookie);
        var sessionId = parseSignedCookie(cks["connect.sid"], config.sessionSecret);

        config.sessionStore.get(sessionId, function(err, session) {
            if (!err) {
                console.info("connected socket for ID " + sessionId);
                config[sessionId] = socket; // set socket to config so that request handlers could emit on it

                socket.on("disconnect", function() {
                    console.info("disconnected socket for ID " + sessionId);
                    delete config[sessionId];
                });
            }
        });
    }
});

For the request handlers to know about the config I write them normally in the following form:

exports.get = function(conn, config) {
    return function(req, res, next) {
        var socket = config[request.sessionID];
        if (socket) {
            // socket.emit 
        }
        res.end();
    }
}

app.get("/", someModule.get(customConnection, config));

For the latter, see more under https://github.com/codelab-io/node-route-dir

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top