2

After successful login, userId and Name of the user are saved in a cookie.

server.js

const io = require('socket.io')(http)
const session = require('express-session')


const Allusers = [ {id: 1, name: 'Admin', username: 'admin', password: 'admin'} ]
const socketName = {}

app.use(session({
    name: 'sid',
    resave: false,
    saveUninitialized: false,
    secret: 'secretCode!',

    cookie: {
        httpOnly: false,    
        maxAge: 1000 * 60 * 60 * 24 * 30, // 1  month
        sameSite: true
    }
}))


// FOR USER LOGIN AND SAVING COOKIE
app.post('/login', (req,res) =>{

    const {username, password} = req.body

    if (username && password){

        const user = Allusers.find(user => user.username === username && user.password === password)
        if (user){
            req.session.userId = user.id
            req.session.name = user.name
            return res.redirect('/')
        }

    }
    res.redirect('/login')
})





io.on('connection', (socket) => {

    //   I WANT TO GET NAME AND ID OF THE USER FROM COOKIE, THEN ADD THEM TO socketName as
    //   {'socket_id' : 'Name of the user'}

});

I want to get name and id of the user from cookie, then add them to socketname as

{'socket_id' : 'Name of the user'}

I'm able to get cookie using socket.handshake.headers.cookie , but it is encrypted using the secret string.

How can I decrypt cookie data or verify the user from Allusers ?

aditya
  • 73
  • 8
  • It seems that someone asked that question before. You can read about sharing session between express and socket.io here: https://stackoverflow.com/a/25618636/3902453. Also if you don't want to use that middleware. You can read about JWT – Rafał Figura Jun 16 '20 at 11:18
  • I already have a signed cookie value. I just want to decode it so I can match it with a stored database. Can I do it without any middleware? – aditya Jun 16 '20 at 13:39
  • If you have cookie, you can parse it with: https://www.npmjs.com/package/cookie-parser `const cookieParser = require('cookie-parser')` `cookieParser.signedCookie( cookie, secret)` – Rafał Figura Jun 17 '20 at 12:13
  • @Sahee Yes, I tried this but it isn't working. cookie value : `s:1ixMMHeWxJ2-MnSNDQpW8lWFKpjQ9Z_s.tD8jPkfgwnwAFI3EjNuZ95LknqGF/hgT07vA6pY315Q`. It returns `1ixMMHeWxJ2-MnSNDQpW8lWFKpjQ9Z_s`. I was expecting a number like 1 or 2 i.e. User ID. CODE : `var cookieData = cookie.parse(socket.handshake.headers.cookie)['sid']` `var a = cookieParser.signedCookie( cookieData, secretKey)` – aditya Jun 17 '20 at 14:05
  • @Sahee Even using the middleware didn't solved the problem. https://stackoverflow.com/a/25618636/3902453. I followed steps here, but I'm unable to access **sid**. After using `socket.request.session`, all I got was : `{"cookie":{"originalMaxAge":2592000000,"expires":"2020-07-17T15:00:30.657Z","httpOnly":false,"path":"/","sameSite":true}}` – aditya Jun 17 '20 at 15:01

1 Answers1

0

For your case, first of all, you need to know that the session id is generated by a generating function - generateSessionId(by default). This means the session id(sid cookie) DOES NOT contain any user data, the user data stored on the server-side(MemoryStore by default). So you should get the user session data from the server-side rather than get them from the sid cookie.

The operations like:

req.session.userId = userId;
req.session.name = name;

The userId and name will be stored in MemoryStore on the server-side.

Now, let's get the session data. The value of socket.request.headers.cookie will be a string like this:

sid=s%3AfWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU%2Fa%2FxVSt4MnqylJJ2LAFb%2B770BItu%2FpFxk; io=msngndIn0v4pYk7DAAAU
  1. we should use cookie.parse(str, options) method to parse string to a JavaScript plain object.
{
  sid: 's:fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU/a/xVSt4MnqylJJ2LAFb+770BItu/pFxk',
  io: 'eeOnxhDIiPSE_0gfAAAm'
}
  1. We should unsign the signed cookie use cookieParser.signedCookie(str, secret) method. Get the unsigned sid:
fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY
  1. Since the default server-side session storage is MemoryStore, you need to initialize it explicitly and call store.get(sid, callback) in the WebSocket connection callback function to get the user session data by sid.

The complete working example:

const session = require('express-session');
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const cookie = require('cookie');

const Allusers = [{ id: 1, name: 'Admin', username: 'admin', password: 'admin' }];
const MemoryStore = new session.MemoryStore();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  session({
    store: MemoryStore,
    name: 'sid',
    resave: false,
    saveUninitialized: false,
    secret: 'secretCode!',

    cookie: {
      httpOnly: false,
      maxAge: 1000 * 60 * 60 * 24 * 30,
      sameSite: true,
    },
  }),
);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

app.post('/login', (req, res) => {
  const { username, password } = req.body;
  console.log(username, password);
  if (username && password) {
    const user = Allusers.find((user) => user.username === username && user.password === password);
    console.log(user);
    if (user) {
      req.session.userId = user.id;
      req.session.name = user.name;
      return res.redirect('/');
    }
  }
  res.redirect('/login');
});

io.on('connection', (socket) => {
  console.log('a user connected');
  const cookieString = socket.request.headers.cookie;
  console.log('cookieString:', cookieString);
  if (cookieString) {
    const cookieParsed = cookie.parse(cookieString);
    console.log('cookieParsed:', cookieParsed);
    if (cookieParsed.sid) {
      const sidParsed = cookieParser.signedCookie(cookieParsed.sid, 'secretCode!');
      console.log(sidParsed);
      MemoryStore.get(sidParsed, (err, session) => {
        if (err) throw err;
        console.log('user session data:', JSON.stringify(session));
        const { userId, name } = session;
        console.log('userId: ', userId);
        console.log('name: ', name);
      });
    }
  }
});

http.listen(3000, () => {
  console.log('listening on *:3000');
});

You will get the session data userId and name like this:

user session data: {"cookie":{"originalMaxAge":2592000000,"expires":"2021-02-14T08:31:50.959Z","httpOnly":false,"path":"/","sameSite":true},"userId":1,"name":"Admin"}
userId:  1
name:  Admin

source code: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/62407074

slideshowp2
  • 38,463
  • 29
  • 127
  • 255