-1

I have a password being hashed and saved in to a SQL database with the following code:

$passHash = password_hash($password, PASSWORD_DEFAULT);

It is saved in to a field called 'password' with the type VARCHAR(255)

I then use the following code to log the user in

$dbconn = OpenCon();
$username = $_POST['usernameInput'];
$password = $_POST['passInput'];
$passHash = password_hash($password, PASSWORD_DEFAULT);
$school = $_POST['schoolInput'];
$sqlstmnt2 = 'SELECT * FROM users WHERE username = :username AND school = :school';
$stmtUsr2 = $dbconn -> prepare($sqlstmnt2);
$stmtUsr2 -> bindValue(':username', $username);
$stmtUsr2 -> bindValue(':school', $school);
$stmtUsr2 -> execute();
$rows = $stmtUsr2 -> fetchAll();
$n = count($rows);
if($n<1 or !password_verify($rows[0]['password'], $passhash)) {
        echo 'No user account exists. Please check your credentials'."<br>";
}
else{
       $_SESSION['username'] = $username;
       header("Location: home.php");
}

When I run it and enter a details I know to be correct, the password_verify function is not returning that they are the same. What am I doing wrong?

IMSoP
  • 89,526
  • 13
  • 117
  • 169
user1480135
  • 157
  • 1
  • 4
  • 16
  • [`PASSWORD_VERIFY()`](https://www.php.net/manual/en/function.password-verify.php) From the Manual The other part of the `password_hash()/password_verify()` pair – RiggsFolly Jul 25 '20 at 17:48
  • 1
    Please check the usage examples. You aren't verifying the actual password but a new hash. If `password_hash()` would always produce the same hash you wouldn't need `password_verify()`, you could simply use `===`. – Álvaro González Jul 25 '20 at 17:51
  • Ah, so I see that I should be passing $password in to the password_verify and not the actual hash. I did that and edited the question but it's still not accepting it – user1480135 Jul 25 '20 at 17:55
  • 1
    `password_verify($_POST['passInput'], $rows[0]['password'])` – RiggsFolly Jul 25 '20 at 17:57
  • I've reverted your edit and answered the question as originally posed. – IMSoP Jul 25 '20 at 17:58
  • I notice you are doing a `$rows = $stmtUsr2 -> fetchAll();` How many rows can be returned by your query, if its more than one, then how do you know you are checking the right users password?? If you can return only one, then dont use fetchAll as that just confuses – RiggsFolly Jul 25 '20 at 18:00
  • @IMSop If I could have found that Duplicate I would have used it, but I couldnt – RiggsFolly Jul 25 '20 at 18:02
  • Thanks @RiggsFolly. I failed to understand that the order in which you pass the values mattered – user1480135 Jul 25 '20 at 18:03

1 Answers1

1

If we break down the code, and look at the main flow without the details, we have something like this:

$passwordFromUserInput = getPasswordFromUserInput(); // $password in your code
$passHash = password_hash($passwordFromUserInput, PASSWORD_DEFAULT);
$passwordHashFromDb = getPasswordHashFromDb(); // $rows[0]['password'] in your code
if ( password_verify($passwordHashFromDb, $passHash) ) {
   // success
}

(I'm assuming that although the database column is called password, it isn't actually storing the raw password, which would defeat the purpose of hashing it!)

But if we look at the signature of password_verify in the PHP manual, it looks like this:

password_verify ( string $password , string $hash )

You're passing in two hashes, but it wants a password (the one the user attempted to log in with) and a hash (the one you've stored). So the corrected version of the simplified code is this:

$passwordFromUserInput = getPasswordFromUserInput(); // $password in your code
$passwordHashFromDb = getPasswordHashFromDb(); // $rows[0]['password'] in your code
if ( password_verify($passwordFromUserInput, $passwordHashFromDb) ) {
   // success
}

Or more succinctly:

if ( password_verify($_POST['passInput'], $rows[0]['password']) ) {
   // success
}

The key to understanding this is that the function is not just comparing two strings. It's using information stored in the original hash (including a random "salt" string) to re-calculate a new hash from the user's input.

IMSoP
  • 89,526
  • 13
  • 117
  • 169