0

I'm trying to set up signing in to the website I'm working on. I'm having trouble finding a user based on their login information as my result is always coming up null.

This is what I have in my users service that passes in the username and password.

confirmUser(username: string, password: string) { 
    this.http.get<{ confirmUser: ConfirmUser }>('http://localhost:3000/users?username=' + username.toLowerCase() + '&password=' + password).subscribe(
        // success function
        (response) => {
           console.log(response);
           return; //Only returning here just to check the response before moving on while I debug
           // this.user = response.user;
           // console.log(this.user);
        }
     ),
     (error: any) => {
        console.log(error);
     } 
}

On the other side of things, I can use this to safely return all users (as long as I remove the required username/password first)

router.get('/', (req, res, next) => {
User.findOne()
.then(user => {
    res.status(200).json({
        message: "Logged in successfully",
        user: user
    });
})
.catch(error => {
    console.log(error);
});
});

The issue comes when I try to filter it down to find the user based on their username, and then check the stored hash against the new hash created from the passed in password. Here is an example of what I have tried:

router.get('/', (req, res, next) => {
const hash = bcrypt.hashSync(req.query.password, saltRounds); //Hash the password argument
User.findOne( { username: req.username }).then(user => { //Find based on username

    if (user){ //Check here to match the hashes before returning?
        res.status(200).json({
            confirmUser: ConfirmUser = {
                id: user.id,
                username: user.username    
            }
        });

    } else {
        res.status(401);
    }

})
.catch(error => {
    // returnError(res, error);
});
});

First, I'm not entirely sure where to compare the two hashes to make sure I'm grabbing the correct user and not one that just has the same username (though I guess making sure usernames be unique would solve that issue)

I know there is a way to return only specific fields from the record that is found, I believe by adding in something to the effect of {username: 1, password: 0}, but I also am not sure how to actually do this. Ideally I would like to find the user that matches the username/password, and then only return the user's ID and username to store to actually log them in. The full User model is as follows:

export class User {
constructor(
    public id: string,
    public firstName: string,
    public lastName: string,
    public username: string,
    public email: string,
    public password: string
) { }
}

The confirmUser object is a view model that only contains those fields:

export class ConfirmUser {
constructor(
    public id: string,
    public username: string,
) { }
}

This may be too many questions in one, but I didn't want to leave anything out that may help solve the issue, as I know that I likely have several problems that need to be addressed here, but I am at a loss for what to do myself.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
hego64
  • 345
  • 1
  • 5
  • 17

1 Answers1

1

This is because your have written. findOne( { username: req.username }).then(user => { //Find based on username

It can be seen that you have by mistake used req.username, which is not defined. And as a result user is null.

So use req.query.username or req.body.username.

Based on route type

Mohit Gupta
  • 368
  • 3
  • 10
  • 1
    Thank you so much for that! Sometimes all it takes is a second pair of eyes. Got everything working now – hego64 Jul 25 '20 at 06:39