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 :
https
server.cookieParser
object with secret phrase (so it "actually" exports the secret phrase to io = new SessionSockets(serverIO, sessionStore, cookieParser);
)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 ?
Socket.IO can be used based on the Express server just as easily as it can run on a standard Node HTTP server. In this section, we will fire the Express server and ensure that it can talk to the client side via Socket.IO.
Both WebSocket vs Socket.io are popular choices in the market; let us discuss some of the major Difference Between WebSocket vs Socket.io: It provides the Connection over TCP, while Socket.io is a library to abstract the WebSocket connections. WebSocket doesn't have fallback options, while Socket.io supports fallback.
socket-io. client is the code for the client-side implementation of socket.io. That code may be used either by a browser client or by a server process that is initiating a socket.io connection to some other server (thus playing the client-side role in a socket.io connection).
Here's my solution for the following environment:
Code:
var cookieParser = require('cookie-parser')();
var session = require('cookie-session')({ secret: 'secret' };
...
app.use(cookieParser);
app.use(session);
...
io.use(function(socket, next) {
var req = socket.handshake;
var res = {};
cookieParser(req, res, function(err) {
if (err) return next(err);
session(req, res, next);
});
});
Then you can access the session from the socket's handshake:
io.on('connection', function (socket) {
console.log("Session: ", socket.handshake.session);
});
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 the session
through the handshake
With the new express-session middleware all you have to do is to add the IO middleware:
io.use(function(socket, next) {
session(socket.handshake, {}, next);
});
A complete example would look like this:
var io = require('socket.io')(server);
var Session = require('express-session'),
SessionStore = require('session-file-store')(Session);
session = Session({
store: new SessionStore({ path: './tmp/sessions' }),
secret: 'pass',
resave: true,
saveUninitialized: true
});
io.use(function(socket, next) {
session(socket.handshake, {}, next);
});
io.on('connection', function(socket){
console.log('a user connected');
socket.emit('chat message', "UserID: " + socket.handshake.session.uid);
});
I created a super mini npm package socket.io-express-session which works as I explained above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With