ufk
ufk

Reputation: 32114

session is undefined using sesssion.socket.io-express4

I'm working on a NodeJs with the following modules:

express 4.9.8

express-session 1.9.3

socket.io 1.2.1

session.socket.io-express4 0.0.3

I'm trying to get a session from session.socket.io-express4 in app.js using the following code:

first the init of the all thing in app.js:

var server = app.listen(3000, function() {
  debug('Express server listening on port ' + server.address().port);
});

var io = require('socket.io')(server);
var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser('bingo');

app.use(session({
secret: 'bingo',
cookie: {httpOnly: true, secure: true, maxAge: new Date(Date.now() + 3600000)},
store: sessionStore,
resave: true,
saveUninitialized: true
}));

var SessionSockets = require('session.socket.io-express4');
sessionSockets = new SessionSockets(io, sessionStore, cookieParserVar);
require('./models/socket.js')(sessionSockets);

my socket.js:

function handleSocket(sessionSockets) {
     sessionSockets.on('connection', function (err, socket, session) {
          console.log("session : " + session);
    });
}

module.exports = handleSocket;

the problem is that session is undefined. any ideas ?

update

so i tried using socket.io-sessions instead.

this is my code:

var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser();

app.use(session({
    secret: 'bingo',
    key: 'express.sid',
    store: sessionStore,
    resave: true,
    saveUninitialized: true
}));

io.set("authorization", socketIoSessions({
    key:    'express.sid',       //the cookie where express (or connect) stores its session id.
    secret: 'bingo', //the session secret to parse the cookie
    store:   sessionStore      //the session store that express uses
  }));

require('./models/socket.js')(io);

and my models/socket.js file includes:

function handleSocket(sock) {
        sock.on('connection',function(socket)
        {
                socket.handshake.getSession(function (err, session) {
                        console.log("HERHERHEHREHREHRHEHERHERHRHERHERHEHREHREHREHR");
                        console.log(session);
                        console.log(err);
                });
                require('../commands/echo.js')(sock);
        });
}

module.exports = handleSocket;

this is the error that I get:

/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/models/socket.js:8
            socket.handshake.getSession(function (err, session) {
                             ^
TypeError: Object #<Object> has no method 'getSession'
at Namespace.<anonymous> (/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/models/socket.js:8:34)
at Namespace.emit (events.js:95:17)
at Namespace.emit (/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/node_modules/socket.io/lib/namespace.js:205:10)
at /mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/node_modules/socket.io/lib/namespace.js:172:14
at process._tickCallback (node.js:419:13)

what am i missing ?

last update

socket.io-session works as expected. the only thing that i needed to change is the authorization callback in order for it to be compatible with socket.io-1.0 i did the following:

io.use(function (socket, next) {
        var handshakeData = socket.handshake;
        ioSession(cookieParser(config.app.session_key), sessionStore)(handshakeData, next);
    }
);

Upvotes: 3

Views: 1631

Answers (1)

Timothy Strimple
Timothy Strimple

Reputation: 23070

update

The explanation of the issue from the original answer is still all relevant, but the fix is much simpler (and more secure). Just use socket.io-session instead. The session.socket.io-express4 module is only necessary if you're using the connect version of cookieParser which doesn't have the same signature handling as the newer cookie-parser does.

original answer

This is due to a bug in sesssion.socket.io-express4 when using both a cookie-parser secret and an express-session secret. What's happening is sesssion.socket.io-express4 is trying to strip the signing off of the connect.sid cookie. You can see that here:

if(handshake.cookies && handshake.cookies[key]) handshake.cookies[key] = (handshake.cookies[key].match(/\:(.*)\./) || []).pop();

The signed cookie looks like this s:<value>.<signature>, and the regex selects anything between : and . which would be the value of the signed cookie. The problem is, cookie-parser will remove the signature itself if you pass in a secret. That means that session.socket.io-express4 is expecting s:<value>.<signature> but is receiving <value> instead so the regex returns undefined. To work around this you could omit the secret from cookie-parser.

I have submitted a pull request to session.socket.io-express4 with a fix for this bug so you have to use a cookie-parser with the same secret as the express-session.

tl;dr

Don't supply a secret to the cookie-parser. The following should work as you expect:

var server = app.listen(3000, function() {
  debug('Express server listening on port ' + server.address().port);
});

var io = require('socket.io')(server);
var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser();

app.use(session({
    secret: 'bingo',
    store: sessionStore,
    resave: true,
    saveUninitialized: true
}));

var SessionSockets = require('session.socket.io-express4');
sessionSockets = new SessionSockets(io, sessionStore, cookieParserVar);
require('./models/socket.js')(sessionSockets);

Upvotes: 3

Related Questions