Login function with PDO

This login function below is working perfectly if I don’t hash my password:

        function Login_Attempt($UserName,$Password){
          global $ConnectingDB;
          $sql = "SELECT * FROM admins WHERE username=:userName AND password=:passWord LIMIT 1";
          $stmt = $ConnectingDB->prepare($sql);
          
            $stmt->bindValue(':userName',$UserName);
            $stmt->bindValue(':passWord',$Password);
            $stmt->execute();
            $Result = $stmt->rowcount();
            if ($Result==1) {
              return $Found_Account=$stmt->fetch();
            }else {
              return null;
            } 
          
        }

but when I hashed my password, I wash trying to verify the user submitted password $Password with $storedPwd in the database before binding username and password like this:

function Login_Attempt($UserName,$Password){
  global $ConnectingDB;
  $sql = "SELECT * FROM admins WHERE username=:userName AND password=:passWord LIMIT 1";
  $stmt = $ConnectingDB->prepare($sql);
  while ($DataRows = $stmt->fetch()) {
    $username = $DataRows["username"];
    $storedPwd = $DataRows["password"];
  }
  $decrypt_password = password_verify($Password, $storedPwd);
  if($decrypt_password == $Password){
    $stmt->bindValue(':userName',$UserName);
    $stmt->bindValue(':passWord',$storedPwd);
    $stmt->execute();
    $Result = $stmt->rowcount();
    if ($Result==1) {
      return $Found_Account=$stmt->fetch();
    }else {
      return null;
    } 
  }else {
    echo "Bad request";
  }
}

Please, help I want to compare the $storedPwd with $Password before binding the username and password but I don’t know how to go about it.

password_verify returns a boolean (true/false); it doesnt decrypt the password, it compares the user’s input to the hashed password and sees if they match.

I wanted to compare the two passwords I just used $decrypt_password as a variable before binding the username and password, my problem is how to fetch the password from database and compare it with $Password before binding and continue with the rest of the code.

So you’ve written the hashed password to the database, with the username.

The user sends you a username and password.

You pull all of the info you need about the user based on the username alone.

You compare the password the user gave you to the hashed one from the database.

If they match, you continue to do your code, with the information you’ve already retrieved.

If they dont, you abort and deny the user’s access. (and clean up the data you retrieved, so the user cant do anything silly with it)

I got your explanation but you did not get mine. my problem really is how do I bind the username and password immediately I compare the StoredPassword with Password to continue to work as before.

You can’t do that. That’s not how the password functions in PHP work. The only way to do it is as @m_hutley already described.

function Login_Attempt($UserName,$Password){
  global $ConnectingDB;
  $sql = "SELECT * FROM admins WHERE username= ?";
  $stmt = $ConnectingDB->prepare($sql);
  $stmt->execute([$UserName]);
  if ($DataRow = $stmt->fetch()) {
    if (password_verify($Password, $DataRow["password"])) {
       return $DataRow;
    } 
  }
  echo "Bad request";
}

(Yes, i keep trimming fat :P)

4 Likes

I personally don’t like passwords leaving this function so I would unset those fields before returning $DataRow. Not sure of the fields being returned but its numeric key should also be unset. I’ll just call it 4.

unset($DataRow[4]);	
unset($DataRow['password']);
return $DataRow;
2 Likes

I’d probably PDO::FETCH_ASSOC and just dump all the numerics to begin with. But yes, slicing the password out is a good call.

I also considered the double-nested if’s, but i dont know that i like using the variable defining bit in the first half of an AND and using it immediately afterward. I know it works, it just feels sketchy.

(Edit: Helps if i remember what the mode type is actually called…)

1 Like

Thanks, very much, you have helped me where I was having trouble,

$stmt->execute([$UserName]);
if($DataRow=$stmt->fetch()) {
  if(password_verify($password, $DataRow["password"]) {
    return $DataRow;
  }
}

I did not know I could write it this way, I was just thinking I had to bind it one by one, but thanks for this great help.

Thanks.

There is no need to bind params in PDO, you can pass the param values into execute as an array.
One of many advantages of using PDO.

But in that case you must be really sure where this array is coming from. If only one array entry is an user input you can get in big trouble…

The statement is pre-prepared, which should elimitate most injection attacks.
Either way, it’s no safer to bind each parameter individually, it just takes more code to make the same result.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.