So I'm learning Loopback for NodeJs and I'm trying to do authentication using bcrypt lib. I need my login remote method to return a null value if the user is not found or the password doesn't match.
My implementation of login is:
User.login = function(username, password,cb){
User.findOne({where:{username: username}}, function(err, user){
cb(null, user);
console.log(JSON.stringify(user));
if(user === null){
console.error('User not found');
return null;
}
console.log('User found');
if(!bcrypt.compareSync(password, user.password)){
console.error('Illegal Password');
user = null;
console.log('USER SHOULD BE NULL =======> '+JSON.stringify(user));
return user;
}
console.log('User Authenticated');
return user;
});
}
In fact the console.log that should be null is actually null if the user is found, however in the auth.service function that should receive the null value if password doesn't match it does receives a user.
login(username: string, password: string) {
return this.http.post(this.configService.apiUrl + '/users/login', { username: username, password:password })
.pipe(map(user =>{
console.log('AUTHSERVICE USER SHOULD BE NULL ===========> '+ JSON.stringify(user));
//THIS USER IS NEVER NULL IF USER IS FOUND!!! EVEN IF PASSWORD IS NOT MATCHED
if(!user || user === null){
console.error('Invalid credentials');
return;
}
sessionStorage.setItem('currentUser', JSON.stringify(user));
this.loggedIn.next(true);
this.router.navigate(['/']);
return user;
}));
}
I'sure I'm missing something here any help would be appreciated it. Thanks.
Please note that LoopBack remote methods are async, therefore the result must be passed via the second callback argument, not as a return value.
User.login = function(username, password,cb){
User.findOne({where:{username: username}}, function(err, user){
// ** DON'T FORGET TO HANDLE ERRORS **
if (err) return cb(err);
console.log(JSON.stringify(user));
if(user === null){
console.error('User not found');
// ** THE FIRST ARG IS "error", THE SECOND ARG IS "result"
cb(null, null);
}
console.log('User found');
if(!bcrypt.compareSync(password, user.password)){
console.error('Illegal Password');
user = null;
console.log('USER SHOULD BE NULL =======> '+JSON.stringify(user));
return cb(null, null);
}
console.log('User Authenticated');
cb(null, user);
});
}
To explain the behavior you are observing: in your implementation of login, you always return the user found by findOne
, see here:
User.findOne({where:{username: username}}, function(err, user){
cb(null, user);
// none of the code below matters, because the result
// has been already set via `cb(null, user)`
}