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.
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!