node.jsauthenticationexpress-sessionnedb

Express session authentification and assigning variables


I am facing weird issue. I believe its very simple to experienced people.

Making local web server on Node.js+Express+NeDB

Client on login makes POST request to /login form and is redirected on successful login. {"id":1,"created":1568146217901,"username":"sprice","name":"Steve Price","email":"email@gmail.com","password":"Password","level":"1","_id":"3JDE7p6tAl1vD11k"} Login post

// POST services
app.post('/login', (req, res) => {
    const loginData = req.body;
    db.users.findOne({ username: loginData.uname }, function (err, doc) {
        req.session.userId = doc.id;
        if(doc.id === 1) console.log("True"); // < Output: True
        console.log(req.session.userId); // < Output: 1
    });
    req.session.userId = 1; // < Just for test
    res.redirect('/plan');
});

Before going into /plan page there is an auth check:

const redirectLogin = (req, res, next) => {
    const { userId } = req.session;
    console.log(userId); // < Output: undefined
    if (!userId) {
        res.render('pages/index');
    } else {
        next()
    }
}

So my weird question, if i assign value from DB which is integer and to test that i have if statement i get req.session.userId = 1, but when client is redirected its req.session.userId = undefined. But if i assign value manually with that test line it works and server issues cookie and i can visit my site with no problems... Am i doing something wrong?


Solution

  • You are missing the fact that the callback to .findOne() is asynchronous and non-blocking. That means that your request handler returns first and THEN, sometime later (after the res.redirect() has already been sent), the callback gets called. So, the callback is too late for the redirect. Instead, you need to do the res.redirect() inside the callback:

    // POST services
    app.post('/login', (req, res) => {
        const loginData = req.body;
        db.users.findOne({ username: loginData.uname }, function (err, doc) {
            if (err) {
                console.log(err);
                res.sendStatus(500);
                return;
            }
            req.session.userId = doc.id;
            if(doc.id === 1) console.log("True"); // < Output: True
            console.log(req.session.userId); // < Output: 1
            res.redirect('/plan');
        });
    });
    

    Depending upon what session store you're using, you may also have to save any changes to your session before you redirect.