3

I am building a MEAN stack chat application. And I want to be able to get express session id inside socket.io on connection handler. I am able to access the socket.handshake.session.id but it is not the same as req.session.id. Further socket.handshake.session.id keeps changing on every socket.

I have tried to solve this by getting session id from req.handshake.cookie by looking for connect.sid key but this key is not defined in there.

const cors = require('cors'),
express = require('express'),
eSession = require('express-session'),
cookieParser = require('cookie-parser'),
MongoStore = require('connect-mongo')(eSession),
sharedsession = require('express-socket.io-session'),
http = require('http'),
bodyParser = require('body-parser'),
socketio = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketio(server);

const port = process.env.PORT || 3000;
//imports
const mongoose = require('./config/dbconnection');

//routes
const user = require('./api/routes/user');

const socketHandle = (io, mStore) => {
   io.on('connection', (socket) => {
     socket.on('join', (options, callback) => {

     console.log(socket.handshake.headers.cookie); //no connect.sid string present
     console.log(socket.handshake.session.id) // has value but keeps changing on each io connection and this id is not the same as req.session.id in an api endpoint method

    });
  }); 

const corsOptions = {
  origin: 'http://localhost:4200',
  optionsSuccessStatus: 200
};

const db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
  secret: 'my-secret',
  resave: true,
  saveUninitialized: true,
  store: mStore
});

app.use(cookieParser('my-secret'));
app.use(session);
io.use(sharedsession(session,{autoSave:true}));

socketHandle(io, mStore);

//body-parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(cors(corsOptions));

app.use('/user', user);

server.listen(port, () => console.log(`listening on http://localhost:${port}`));

Both socket.handshake.session.id and socket.handshake.headers.cookie(connect.sid key)should have provided the session id that has the same value as req.session.id

Anand Kashyap
  • 63
  • 1
  • 9

3 Answers3

2

@Anand Kashyap is correct, if you let the express server serve your client, the cookie will be present.

However when your client is on a different host, you need to pass withCredentials: true to the socket's constructor. This will attach the cookie to the request and the session will work.

const io = require("socket.io-client");

const socket = io("ws://example.com/", {
  withCredentials: true,
  autoConnect: 10000
});
Alex Tenev
  • 21
  • 1
  • 3
1

I tried it out and it worked for me with your code so I think there is something with your session storing. Seems like there is no interaction between your socket.handshake.session and your express-session, maybe because you are not storing it properly in mongo. Try this out and then build your app around it :)

const express = require('express');
const eSession = require('express-session');
const MongoStore = require('connect-mongo')(eSession);
const mongoose = require('mongoose');
const sharedsession = require('express-socket.io-session');
const http = require('http');
const socketio = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketio(server);

const port = process.env.PORT || 3000;

const socketHandle = (io) => {
   io.on('connection', (socket) => {
     console.log(socket.handshake.session.id) // same value on every connection
  }); 
}

// Connect with MongoDB (database called 'test')
mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useCreateIndex: true })
    .then(() => console.log('Connected with MongoDB!'))
    .catch(err => console.log(err));

let db = mongoose.connection;

const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
  secret: 'my-secret',
  resave: true,
  saveUninitialized: true,
  store: mStore
});

app.use(session);
io.use(sharedsession(session,{autoSave:true}));

socketHandle(io);

// Static folder
app.use(express.static('public')); //Basic html page for socket connection

server.listen(port, () => console.log(`listening on http://localhost:${port}`));

Now if you look in your session collection you will see that it is stored and the id is the same as the handshake.session.id. Hope this works for you :)

Djinii
  • 31
  • 1
  • 8
  • Djinii is it necessary to use app.use(express.static('public')) for having the same socket id? I am trying to connect with socket via ng serve on a different port. – Anand Kashyap Sep 03 '19 at 13:30
  • No it is not necessary. I just did it to try it out. Be sure your port is the same when you listen on another port. – Djinii Sep 05 '19 at 12:20
  • @Djinii I tried your example and am getting different session_ids, console-log: "KOyRyj5icAr3FUWpvoRSoEC3EhZueBZV" and in Mongo "0nkOKn5HaUIWg6adm0SaOSRDoSMnh1wR" - how come? I am pulling my hair here... – Fabian Bosler Apr 14 '20 at 23:35
1

There was not any issue with my code. The only thing that was causing different session id was the fact that I was running angular on a different port than node server. I had to ng build --watch for angular and output the files in node server's static files folder. By doing this, I was able to get consistent session id both in routes and socket io.

Anand Kashyap
  • 63
  • 1
  • 9
  • I am having the exact same problem here: socket.handshake.session.id: "-armMd830gjfhLP7BRXXK3rLWeDDLlNu" socket.handshake.headers.cookie: "io=s_h5pcLB_9NSXUHLAAAA" You seemed to have solved it, could you explain your answer a little bit more? I also used the build files for the static information, but no luck. – Fabian Bosler Apr 14 '20 at 23:41
  • @FabianBosler are you keeping the frontend files in static directory of expressjs or not? – Anand Kashyap Apr 15 '20 at 05:05
  • Jupp, I am. Yarn build and reference that folder. – Fabian Bosler Apr 15 '20 at 05:41
  • Socket id should have been same then. At least after building frontend. Can you share your code of express doing socket connection and checking id – Anand Kashyap Apr 19 '20 at 04:05