Search code examples
node.jsmongoosepassport.jspassport-local

passport.js post login return not called


I've been trying to set up a server on as back-end for an android application. Using secure & authoritative RESTful api is hopefully a core functionality.

Now I have recently discovered passport, and I after quite some struggles (specifically with callbacks), I have finally found myself fully stuck.

I have a pretty much "exact" match between my POST register functionality (which works) and my POST login functionality (which works up until the return done(null, user), which just doesn't get called it seems.

All code is visible: https://github.com/mathieudevos/pinkiponki

So in routes.js

//Login
    router.post('/login', passport.authenticate('login', {failWithError: true}),
        function(req, res, next){
            // Handle success
            log('Everything went ok. ' + req.user.username); //This never gets called, timeout before.
            httpResponses.sendLoginOK(res, req.user.username);
            return ;
        },
        function(err, req, res, next){
            // Handle error
            return res.json(err);
        }
    );

    //Register
    router.post('/register', passport.authenticate('register', {failWithError: true}),
        function(req, res, next){
            // Handle success
            httpResponses.sendRegisterOK(res, req.user.username);
            return ;
        },
        function(err, req, res, next){
            // Handle error
            return res.json(err);
        }
    );

Login.js:

// login!
    passport.use('login', new localStrategy({
        passReqToCallback: true
    },
    function(req, username, password, done) {
        users.findOne({'username': username}, function(err, user){
            if (err){
                log('Error: ' + err.toString());
                return done(err);
            }
            if (!user) {
                log('Could not find user');
                return done(null, false, {message: 'Fail login: ' + username});
            } 
            if (!user.validatePassword(password)) {
                log('Wrong password');
                return done(null, false, {message: 'Fail login: ' + username});
            }
            log('All is good! \n' + user.toString());
            return (null, user);
        });
        }
    ));

And register:

// register!
    passport.use('register', new localStrategy({
        passReqToCallback: true
    },
    function(req, username, password, done) {
        users.findOne({username: req.body.username}, function(err, user){
            if (err){
                return done(null, false, {error: err.toString()});
            }
            if (user){
                // User already exists
                return done(null, false, {message: 'User already exists'});
            }
            if(password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && password.length > 4 && password.match(/[0-9]/) && password.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)){
                var newuser = new users({
                    username: username,
                    email: req.body.email,
                    firstname: req.body.firstname,
                    lastname: req.body.lastname,
                    password: generateHash(password),
                    about: req.body.about,
                    rating: 1200
                });
                newuser.save(function (err){
                    if (err) {return done(null, false, {error: err.toString()});}
                    return done(null, newuser, {username: username});
                });
            } else {
                return done(null, false, {message: 'Password not strong enough.'});
            }
        });
    }));


    // generate hash (bcrypt)
    var generateHash = function(password){
        return bCrypt.hashSync(password, bCrypt.genSaltSync(10));
    };

If I run:

curl -x POST http://localhost:9721/register -d '{"username": "Testname", "email":"test@email.com","password":"123@abC","firstname":"test","lastname":"super","about":"this is a test."}' -H 'Content-Type: application/json'

I am welcomed with username: testname

Now if I run the simple login:

curl -x POST http://localhost:9721/login -d '{"username": "Testname", "password": "123@abC"}' -H 'Content-Type: application/json'

Then my log shows it's nicely going through the steps in my login part and my logs even show that user.toString() is the right user.

Now the return(null, user) seems to hang fully and the functionality in routes.js is never called (thus my httpResponses are never called either).

Anybody has any ideas on how to deal with this?

Also any documentation on how to just respond to the user with simple json message (I already tried the failWithError, but the only thing I get out of it is unAuthorized 401, I can't have any custom messages).

The idea is to set all this up to use with retrofit (RESTful JSON) on Android and use this functionality of passport/nodejs/mongoose as a back-end for my application.

If you need any more code, I'll happily provide any more code.


Solution

  • Instead of return (null, user) you need to call

    return done(null, user)
    

    or just

    done(null, user)
    

    in your login.js

    Hope it helps!