Session undefined using sesssion.socket.io-express4
I am working on 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 am trying to get session from session.socket.io-express4 in app.js using the following code:
first initialize everything 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 the 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 in my models file /socket.js:
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 i am getting:
/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 I needed to change was the authorization callback to be socket.io-1.0 compatible, I did the following:
io.use(function (socket, next) {
var handshakeData = socket.handshake;
ioSession(cookieParser(config.app.session_key), sessionStore)(handshakeData, next);
}
);
source to share
Update
The explanation for the problem from the original answer is still valid, but the fix is ββmuch easier (and safer). Use socket.io-session instead. The session.socket.io-express4 module is only needed if you are using a version of the cookieParser connection that does not have the same signature handling as the new cookie parser.
original answer
This is due to a bug in sesssion.socket.io-express4 when using secret cookie-parser and express session secret. What happens is sesssion.socket.io-express4 is trying to revoke the signing 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 s:<value>.<signature>
and the regex chooses anything between :
and .
which will be the value of the signed cookie. The problem is that the cookie-parser will remove the signature if you pass the secret. This means that session.socket.io-express4 expects s:<value>.<signature>
but receives instead <value>
, so the regex returns undefined. To get around this, you can omit the secret from the cookie-parser.
I sent a request to session.socket.io-express4 with a fix for this error, so you need to use a cookie parser with the same secret as the express session.
TL; DR
Don't expose the 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);
source to share