I would like to access the express 4 session in my socket.io app. I'm kind of new with Node and I have some troubles implementing this functionality.
I found a npm module that allows access to the express 4 session : https://www.npmjs.org/package/session.socket.io-express4 or https://github.com/eiriklv/session.socket.io
If you look at my app.js code below, I'm doing something wrong in the session
, sessionStore
or cookieParser
setup because I just can't get this module working.
// init modules
var express = require('express');
var helmet = require('helmet');
var fs = require('fs');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var memoryStore = session.MemoryStore;
var app = express();
// set variables
var options = {
key: fs.readFileSync('./openssl_keys/server_key.pem'),
cert: fs.readFileSync('./openssl_keys/server_cert.pem')
};
var cookieSecret = "secret phrase";
var sessionStore = new memoryStore();
app.set('env', process.env.NODE_ENV || 'development');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser(cookieSecret));
app.use(session({
secret: cookieSecret,
cookie: {httpOnly: true, secure: true},
store: sessionStore
}));
app.use(function(req, res, next){
res.locals.session = req.session;
next();
});
app.use(express.static(path.join(__dirname, 'public')));
//routes
require('./routes/index')(app);
require('./routes/test')(app);
// starting http and https servers
var http = require('http').createServer(app).listen(8000, function(){
console.log("http server listening on port 8000");
});
var https = require('https').createServer(options, app).listen(8080, function(){
console.log("https server listening on port 8080");
});
// starting socket.io & session handler
var serverIO = require('socket.io').listen(https);
var SessionSockets = require('session.socket.io-express4');
var io = new SessionSockets(serverIO, sessionStore, cookieParser);
io.on('connection', function(err, socket, session){
if(err) throw err;
console.log("connected");
//console.log(session);
socket.on('clientMessage', function(content) {
console.log("received client message")
console.log(content);
});
});
module.exports = app;
I tried multiples possibilities like :
- Disabling
https
server. - Setting up a
cookieParser
object with secret phrase (so it "actually" exports the secret phrase toio = new SessionSockets(serverIO, sessionStore, cookieParser);
) - Using minimal
cookie
options.
Anyway I'm a bit lost with this, any suggestions/critics are welcome.
UPDATE
Ok so after numerous tries I think I could get it work!
The problem is with the cookieParser initialization which the correct way seems to be :
var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(session({
secret: "secret phrase",
cookie: {httpOnly: true, secure: true},
store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());
Notice that if I use var io = new SessionSockets(serverIO, sessionStore, cookieParser);
(instead of cookieParser()
) then it ain't working. That seems to be the problem.
If I use :
app.use(cookieParser("secret phrase"));
app.use(session({
secret: "secret phrase",
cookie: {httpOnly: true, secure: true},
store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser("secret phrase"));
then the module crashes with the following error message :
session.socket.io-express4/session.socket.io.js:41
ake.signedCookies[key] = handshake.signedCookies[key].match(/\:(.*)\./).pop();
^
TypeError: Cannot call method 'pop' of null
But if I use :
app.use(cookieParser("secret phrase"));
app.use(session({
secret: "secret phrase",
cookie: {httpOnly: true, secure: true},
store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());
Then everything looks fine.
Now in the cookie-parser doc (https://github.com/expressjs/cookie-parser) it's saying you can pass a secret key to get the cookies signed. Which is something I'd like to have.
Could someone explain me the relation with the cookie-parser secret phrase and the session secret phrase ? Do they have to be the same/different ?
it gave me a hard time to find the right solution. Here is what works for me :
express 4.2.0 / socket.io 1.0.6
This may work express 4 / socket.io 1.X I grabbed this code form https://github.com/turbonetix/bus.io/blob/master/demo/chat/app.js
Here's my solution for the following environment:
Code:
Then you can access the session from the socket's handshake:
For people wondering how/why this works:
handshake
request through the cookie parser so that cookies are availablehandshake
through session middleware as if its a normal requestsession
to the requesthandshake
because for all intents and purposes, it is a normal request, and the parser and session middleware can deal with it properly. This is why you must access thesession
through thehandshake
express 4.13.4 / socket.io 1.4.5
I browse all solutions and modules, but them all not working in my app. Finaly -
working like a charm.
With the new express-session middleware all you have to do is to add the IO middleware:
A complete example would look like this:
I created a super mini npm package socket.io-express-session which works as I explained above.
express-socket.io-session is a ready-made solution for your problem. Normally the session created at socket.io end has different sid than the ones created in express.js
Before knowing that fact, when I was working through it to find the solution, I found something a bit weird. The sessions created from express.js instance were accessible at the socket.io end, but the same was not possible for the opposite. And soon I came to know that I have to work my way through managing sid to resolve that problem. But, there was already a package written to tackle such issue. It's well documented and gets the job done. Hope it helps