socket.io and session?

node.jsExpressSessionsocket.io

node.js Problem Overview


I'm using express framework. I want to reach session data from socket.io. I tried express dynamicHelpers with client.listener.server.dynamicViewHelpers data, but i can't get session data. Is there a simple way to do this? Please see the code

app.listen(3000);

var io = require('socket.io');
var io = io.listen(app);

io.on('connection', function(client){
    // I want to use session data here
	client.on('message', function(message){
        // or here
	});
	client.on('disconnect', function(){
        // or here
	}); 
});

node.js Solutions


Solution 1 - node.js

This won't work for sockets going over the flashsocket transport (it doesn't send the server the needed cookies) but it reliably works for everything else. I just disable the flashsocket transport in my code.

To make it work, in the express/connect side, I explicitly define the session store so I can use it inside socket:

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

Then inside my socket code, I include the connect framework so I can use its cookie parsing to retrieve the connect.sid from the cookies. I then look up the session in the session store that has that connect.sid like so:

var connect = require('connect');
io.on('connection', function(socket_client) {
  var cookie_string = socket_client.request.headers.cookie;
  var parsed_cookies = connect.utils.parseCookie(cookie_string);
  var connect_sid = parsed_cookies['connect.sid'];
  if (connect_sid) {
    session_store.get(connect_sid, function (error, session) {
      //HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
    });
  }
});

You can then use the session as needed.

Solution 2 - node.js

The Socket.IO-sessions module solution exposes the app to XSS attacks by exposing the session ID at the client (scripting) level.

Check this solution instead (for Socket.IO >= v0.7). See docs here.

Solution 3 - node.js

I suggest not to entirely reinvent the wheel. The tools you need is already an npm package.I think this is what you need: session.socket.io I am using it in these days and it will be very helpful I guess!! Linking the express-session to the socket.io layer will have so many advantages!

Solution 4 - node.js

Edit: After trying some modules that didn't work, I've actually gone and written my own library to do this. Shameless plug: go check it out at https://github.com/aviddiviner/Socket.IO-sessions. I'll leave my old post below for historical purposes:


I got this work quite neatly without having to bypass the flashsocket transport as per pr0zac's solution above. I am also using express with Socket.IO. Here's how.

First, pass the session ID to the view:

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

Then in your view, link it in with Socket.IO client-side:

<script>
  var sid = '<%= connect_sid %>';
  var socket = new io.Socket();
  socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>

Then in your server-side Socket.IO listener, pick it up and read/write the session data:

var socket = io.listen(app);
socket.on('connection', function(client){
  client.on('message', function(message){
    session_store.get(message.sid, function(error, session){
      session.pings = session.pings + 1 || 1;
      client.send("You have made " + session.pings + " pings.");
      session_store.set(message.sid, session);  // Save the session
    });
  });
});

In my case, my session_store is Redis, using the redis-connect library.

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

Hope this helps someone who finds this post while searching Google (as I did ;)

Solution 5 - node.js

See this: https://stackoverflow.com/questions/4753957/socket-io-authentication/4782933#4782933

I would suggest not fetching anything via client.request... or client.listener... as that is not directly attached to the client object and always point to the last logged in user!

Solution 6 - node.js

For future readers - There is an elegant and easy way to access the session inside socket.io with express-session. From socket.io documentation: >Most existing Express middleware modules should be compatible with Socket.IO, you just need a little wrapper function to make the method signatures match:

 const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);

>The middleware functions that end the request-response cycle and do not call next() will not work though.

>Example with express-session:

const session = require("express-session");
io.use(wrap(session({ secret: "cats" })));
io.on("connection", (socket) => {
   const session = socket.request.session; // here you get access to the session :)
});
 

Solution 7 - node.js

Check out Socket.IO-connect

Connect WebSocket Middleware Wrapper Around Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect

This will allow you to push the Socket.IO request(s) down the Express/Connect middleware stack before handling it with Socket.IO event handlers, giving you access to the session, cookies, and more. Although, I'm not sure that it works with all of Socket.IO's transports.

Solution 8 - node.js

I am not sure that I am doing it right. https://github.com/LearnBoost/socket.io/wiki/Authorizing

With the handshake data, you can access to the cookies. And in the cookies, you can grab connect.sid which is the session id for each client. And then use the connect.sid to get the session data from database (I am assuming you are using RedisStore)

Solution 9 - node.js

You can make use of express-socket.io-session .

Share a cookie-based express-session middleware with socket.io. Works with express > 4.0.0 and socket.io > 1.0.0 and won't be backward compatible.

Worked for me!!

Solution 10 - node.js

As of February 2022 this is supported by Socket.IO v4:

https://socket.io/docs/v4/faq/#usage-with-express-session

const express = require('express');
const session = require('express-session');
const app = express();

const server = require('http').createServer(app);
const io = require('socket.io')(server);

const sessionMiddleware = session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }});
// register middleware in Express
app.use(sessionMiddleware);
// register middleware in Socket.IO
io.use((socket, next) => {
  sessionMiddleware(socket.request, {}, next);
  // sessionMiddleware(socket.request, socket.request.res, next); will not work with websocket-only
  // connections, as 'socket.request.res' will be undefined in that case
});

io.on('connection', (socket) => {
  const session = socket.request.session;
  session.connections++;
  session.save();
});

const port = process.env.PORT || 3000;
server.listen(port, () => console.log('server listening on port ' + port));

Solution 11 - node.js

You can have a look at this: https://github.com/bmeck/session-web-sockets

or alternatively you can use:

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsfsView Question on Stackoverflow
Solution 1 - node.jspr0zacView Answer on Stackoverflow
Solution 2 - node.jsJefferView Answer on Stackoverflow
Solution 3 - node.jsFrancescoView Answer on Stackoverflow
Solution 4 - node.jsDaveView Answer on Stackoverflow
Solution 5 - node.jsShripad KrishnaView Answer on Stackoverflow
Solution 6 - node.jsSergei HronovView Answer on Stackoverflow
Solution 7 - node.jsBMinerView Answer on Stackoverflow
Solution 8 - node.jsTan NguyenView Answer on Stackoverflow
Solution 9 - node.jsnonybrightoView Answer on Stackoverflow
Solution 10 - node.jsMaria Ines ParnisariView Answer on Stackoverflow
Solution 11 - node.jsintellidiotView Answer on Stackoverflow