1

I am building an integration with Express Session and I am trying to authenticate the user in a separate webhook. So I need a way to update the user session outside of the request since it would be a different request.

What I did is I passed the session ID to the new request, and use MongoClient to update the session in the database. I remember Express Session only stores the ID on the client-side and the data is store on the database, so I assume updating the database would do it. But that doesn't seem to be the case. I can clearly see that the session on MongoDB is all updated but I kept getting the outdated data in req.session.data.

Here's what I've done

So the first thing I tried is to use the req.session.reload() method like these:

Updating express-session sessions

change and refresh session data in Node.js and express-session

But it is still giving me outdated data as if the function did nothing (it did print out logs so I assume it did run).

I tried using this that uses store.get() method from Express Session but it is giving me undefined session.

Express load Session from Mongo with session_id

So as a last resort I use MongoClient to get the session data directly and update the session with the data obtained. I use async for the route handler and await the MongoClient to get the data. It doesn't wait for the await and just kept throwing undefined. I thought it's my code that's wrong but I am able to get user data with the code and it did wait for the MongoClient to get the data, but somehow it is not working for session data.

Here's part of my code:

app.router.get('/login', async function (req, res, next) {
  req.session.auth = await mongo.getCookie(req.session.id).auth;
  req.session.user = await mongo.getCookie(req.session.id).user;
  console.log('Login Action', req.session.id, req.session.auth, req.session.user);
}
module.exports.getCookie = async function getCookie(identifier) {
  try {
    let database = client.db('database');
    let collection = await database.collection('sessions');
    let result = await collection.findOne({ _id: identifier }, function(err, res) {
      if (err) throw err;
      return res;
    });
    return result;
  }
  catch (err) {
    console.error(err);
    return null;
  }
}

Here's other answers that I've check

This one only update the expiration so I assume its not going to work for me, I did set the resave to false so that it doesn't try to save every single request, since its saving to the database I assume it has nothing to do with updating and I have tried setting it to true and nothing happened.

Renewing/Refreshing Express Session

And in this it uses socket.io and store.get() so it's not going to work as well.

How to access session in express, outside of the req?

Can someone guide me on how do I get Express Session to update from the database or is there a way to get the data from the database and update the session that way?

Anthony Kung
  • 373
  • 2
  • 4
  • 15

1 Answers1

0

So I did eventually figured it out, turns out the session was not updated from the database. Looks like it has a local copy in the cache, but I was under the impression that the express session only uses the database.

I know for a fact that my data is indeed in the database but not in the cache or wherever the local copy of the express session is stored. So the easiest way to get pass this problem is to update the local copy with the data on the database.

And I created this function to update the session data

async function sessionUpdate(req) {
  try {
    // get the data on the database
    let tempSession = await mongo.getCookie(req.session.id);

    // if the data exist, we can copy that to our current session
    if (tempSession) {
      req.session.auth = tempSession.auth;
      req.session.user = tempSession.user;
      
      // you can do other stuff that you need to do with the data too
      if (req.session.health == null || req.session.health == undefined || typeof req.session.health === 'undefined') {
        req.session.health = 0;
      }

      // This update and save the data to the session
      req.session.save( function(err) {
        req.session.reload( function (err) {
          //console.log('Session Updated');
        });
      });
    }
    else if (!tempSession) {
      req.session.auth = false;
      req.session.user = null;
      req.session.ip = request.connection.remoteAddress;
    }
  }
  catch (err) {
    console.error(err);
  }
}

Now that we have a function that can update the session data, we need to implement it everywhere. I use middleware to do that, you can use other methods too but this must be called before the route or the session logic.

// middleware with no mounted path so it is used for all requests
receiver.router.use(async function (req, res, next) {
  try {
    await sessionUpdate(req);
  }
  catch (err) {
    console.error(err);
  }
  next();
});

It's not exactly a good/efficient way of doing it... that's a lot of things to run before even getting to the route so I would assume it would bring the performance down a bit... But this is how I get it to work and if anyone can come up with some better idea I would very much appreciate it

Anthony Kung
  • 373
  • 2
  • 4
  • 15