0

Im having the problem that when the login form is submitted, the application hangs and doesn't get redirected.

I have tried debugging the issue but I can't figure out what's going on.

So far what I have found is (on login submit) the following are called:

Login POST:

router.post('/login', passport.authenticate('local-login', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/login', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
}) );

Middleware gets called, but the redirects never occur.

Authentication using (passport-local) LocalStrategy:

passport.use(
    'local-login',
    new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    function(req, email, password, done) { // callback with email and password from our form
        connection.query("SELECT * FROM users WHERE email=?",[email], function(err, rows){
            if (err)
                return done(err);
            if (!rows.length) {
                return done(null, false, req.flash('login', 'Oops! Wrong email or password')); // req.flash is the way to set flashdata using connect-flash
            }

            // if the user is found but the password is wrong
            if (sha1(password) != rows[0].password) {
                return done(null, false, req.flash('login', 'Oops! Wrong email or password')); 
            }

            // all is well, return successful user
            return done(null, rows[0]);
        });
    })
);

Debug shows that this executes successfully.

SerializeUser:

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.serializeUser receives user object as expected.

DeserializeUser:

passport.deserializeUser(function(id, done) {
    connection.query("SELECT * FROM users WHERE id=? ",[id], function(err, rows){
        done(err, rows[0]);
    });
});

Here I'm not sure what happens. The application hangs. While debugging, I can't get past the following line:

break in net.js:587
 585   // procedure. No need to wait for all the data to be consumed.
 586   self.emit('_socketEnd');
>587 }
 588 
 589 
debug> n
debug> n

I keep pressing 'n' or 'c' but nothing happens.

Can I get some advice on what I'm missing?

Also, can someone help me better understand what the done function does in these authentication methods?

UPDATE:

Function to check that user is logged in:

function isLoggedIn(req, res, next) {

    if (req.isAuthenticated()) {
        return next();
    }

    res.redirect('/login'); 
}

1 Answers1

0

You need to pass control to the next possible route based on un/successful authentication and you need to do that using next(). So try this

router.post('/login', passport.authenticate('local-login', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/login', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
})(req, res, next) ); 

To understand done() refer this answer https://stackoverflow.com/a/32154771/7096322

router.post('/login', function (req, res, next) {
        passport.authenticate('local', function(err, user, info) {
            if(err)
                res.status(500).json({status: 'error', message: 'Something went wrong'});
            if(!user) {
                res.status(401).json(info);
            }
            else {
                req.logIn(user, function (err) {
                    if(err)
                        res.status(500).json({status: 'error', message: 'Something went wrong'});
                    else {
                        req.session.user = user;
                        req.session.save(function (err) {
                            if (err) {
                                console.log(err);
                            } else {
                                res.status(200).json({status: 'success', message: 'Login successful'});
                            }
                        });
                    }
                })
            }
        })(req, res, next);
    }
);


passport.use(new LocalStrategy({
        passReqToCallback: true
    },
    function(req, username, password, done) {
        User.forge({ username: username.trim() })
            .fetch()
            .then(function(user) {
                if(!user) {
                    done(null, false, {status: 'error', message: 'Invalid username'});
                }
                else {
                    bcrypt.compare(password, user.get('password'), function (err, res) {
                        if(res === true) {
                            done(null, user);
                        }
                        else {
                            done(null, false, {status: 'error', message: 'Invalid password'});
                        }
                    })
                }
            })
            .catch(function(err) {
                console.log(err);
                done(err);
            });
    }
));

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.forge({ id: id })
        .fetch()
        .then(function (err, user) {
            done(err, user);
        });
});
zerosand1s
  • 750
  • 1
  • 8
  • 23
  • When I try this, I get error 'ReferenceError: req is not defined'. I tried `router.post('/login', passport.authenticate('local-login', { successRedirect : '/', // redirect to the secure profile section failureRedirect : '/login', // redirect back to the signup page if there is an error failureFlash : true // allow flash messages }), function(req, res, next) { next(); } );` But the callback is never called, still handing. – Sebastian Botero Aug 14 '18 at 13:23
  • are you sure you are getting the user from a database? I have edited my answer please refer to it. – zerosand1s Aug 14 '18 at 17:32
  • I am getting the user back from the database. After running your code, I am getting success status with the login successful message, but when I try requesting a page that requires authentication, it hangs. I think it has something to do with the `req.isAuthenticated()`. I can't find why it hangs here though. – Sebastian Botero Aug 27 '18 at 10:51
  • I am not sure why it's not working but check out the answer for this question https://stackoverflow.com/questions/29111571/passports-req-isauthenticated-always-returning-false-even-when-i-hardcode-done. If not share more code here – zerosand1s Aug 27 '18 at 18:01