PHP Password_Verify Not Working with Database

PHP password_verify() doesn't work with MySQL

This may help you
php password_verify not working with database

Check whether the hash is getting stored in database properly or not.
Dump the hash you are getting from database and hashed password and check are they same or not.

password_verify not working php

Given the code from your original question and the code from your comment, you seem to use password_hash() and password_verify() correctly, and I could not detect another obvious error with the overall structure of your code, so I suspect something weird is going on with the data itself.

For example, it could be that your SELECT returns more than one row (if you haven't set a unique index on the username column, there could be two users with identical username, but different password - you did not show us the table structure / indices).

To debug this further, I suggest to alter your code like that:

if (isset($_POST['submit'])) {

$username = $_POST['username'];
$password = $_POST['password'];

$q = $handler->prepare('SELECT * FROM users WHERE username = ?');
$q->execute(array($username));

if ($q->rowCount() > 0){

error_log((string) ($q->rowCount()));

$result = $q -> fetch(PDO::FETCH_ASSOC);
$hash_pwd = $result['password'];
$hash = password_verify($password, $hash_pwd);

error_log($hash_pwd);
error_log($hash);
error_log((int) $hash);

if ($hash == 0) {

error_log("hashwrong");
echo '<p class="error-message3">'.'<br>'.'<br>'."You have ented an incorrect login! <br>Please try again.".'</p>';
}
else {

$_SESSION['username'] = $username;
error_log("loggedin");
header("location: index.php");return;
}
}
}

Please let us know what the error_log() statements dump out. To make it readable, you could edit your question and append the results at the end (instead of putting it into a comment). But please don't alter that parts of the question which are already referenced by comments or answers (otherwise, later readers won't be able to make any sense from that all).

EDIT 1

I have noticed a possible error in your code. The reason why I did not see it immediately is that I never have used PHP.

However, you should not use ::rowCount() to check if a SELECT statement returns any rows. From the ::rowcount reference in the PDO manual:

PDOStatement::rowCount() returns the number of rows affected by the
last DELETE, INSERT, or UPDATE statement executed by the corresponding
PDOStatement object.

If the last SQL statement executed by the associated PDOStatement was
a SELECT statement, some databases may return the number of rows
returned by that statement. However, this behaviour is not guaranteed
for all databases and should not be relied on for portable
applications.

On the other hand, from the ::fetch reference in the PDO manual:

The return value of this function on success depends on the fetch
type. In all cases, FALSE is returned on failure.

So could you please delete the existing line

$result = $q -> fetch(PDO::FETCH_ASSOC);

and replace

if ($q->rowCount() > 0) {

by

$result = $q -> fetch(PDO::FETCH_ASSOC);
if ($result !== FALSE) {

and tell us the result?

If this does not log any error message (except the PHP warning), then we know that the SELECT does not return any rows for some reason. Remember, according to the section from the manual shown above, chances are that the SELECT did not return rows, but that $q->rowCount() was greater than 0 nevertheless.

If it still does log the error messages, we'll have to do additional debugging.

EDIT 2

We now know that your SELECT returns a row and that there is no problem with fetching the data. Now I am running out of options myself.

IMHO, there is only one explanation left: $password is indeed wrong (from the code's point of view). Such a thing eventually could happen if the encoding of the POST request is wrong. To decide, we could do the following steps:

1) For testing purposes, insert a new user into the users table. This user's username and password shall contain characters from the ASCII range only. For example chose 'AAAAA...' as username (append further 'A' characters until the username is unique) and 'B' as password.

Then run your script again with that username / password, and let us know what happened.

The sense of this test is to prevent problems which might arise due to inappropriate string / POST data encoding / decoding.

2) Insert two more lines to your code:

error_log($username);
error_log($password);

Put these lines at the same place where the other error_log() calls are, and check if this really outputs exactly what you expect, i.e. exactly and literally the values you are POSTing to the script (i.e. the values you have input into your form before submitting it).

Let us know what these two lines output.

3) If the test described in 1. works:

Make sure that the HTML page from where your script is called has explicitly set the correct encoding. For example, have something like

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />;

in your HTML header (please note that this is for XHTML; the syntax or header might be different for HTML 5 or HTML 4.x; you'll have to research that).

Please let us know what happens then.

4) If the test described in 1. works:

I don't know how you actually call that script, but in any case, additionally set the correct encoding when calling the script. For example, if you are calling the script via AJAX, do something like

request.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");

If you are calling it "directly" from a form, then do something like

<form method="post" enctype="..." accept-charset="UTF-8">

Please let us know what happens then.

5) If the test described in 1. works:

Make sure that your web server does not override the encoding which is set in the HTML pages. How you configure the server depends on the server software. For Apache, disable all AddDefaultCharset directives (by commenting them out).

Please let us know what happens then.

EDIT 3

The error is in your upload code. You are using $pass in hash_password(), but $pass is not initialized anywhere. So just add

$pass=$_POST['password'];

after the already existing line

$username=...;

Then create a new username / password combination and try to login using your current login code (but remember to check again if the parameters to password_verify() are in the right order). It should work then.

PHP password_verify not working against database

The \n in the following line, is embedding a linebreak, (Edit: one that cannot be included in the user inputted password).

$password = password_hash($pass,  PASSWORD_BCRYPT, $options)."\n";

and you need to delete it and start over with a new hash.

Jay Blanchard, a member here on Stack submitted a note about it not too long also in the password_hash() manual, which is something that he and I actually talked about.

Be care when using the example from the documentation which concatenates a newline character \n to the end of the hash, i.e.:

echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";

People are storing the hash with the concatenated newline and consequently password_verify() will fail.

Another option would be to use trim(); that also works (at the moment of hashing).

$password = password_hash($pass,  PASSWORD_BCRYPT, $options)."\n";
$password = trim($password);
// Store in db after

Yet you still need to start over by clearing the old hash(es) and creating new ones.

Do keep in mind though, that you shouldn't escape passwords.

One such as 123'\abc (being perfectly valid) will be modified to 123\'\abc by real_escape_string(); it's not needed. password_verify() takes care of that, security-wise.

PHP password_verify() not working with database

You're inserting a hashed password, that's good.
But then on login you're comparing the one on the POST string with the hashed version in the database. Logically, they will not be the same.
You should change :

SELECT * FROM UserName where userName = '$_POST[user]' AND pass = '$_POST[pass]'"

into

SELECT * FROM UserName where userName = '$_POST[user]'

And indeed you should add protection against SQL injection everywhere. Preferably use prepared statements, on every select, insert, update, delete, etc. and on every single value you're using in those statements.

password_verify() not working with database

password_verify returns a boolean.

If login is invalid echoing a false value will print nothing.

password_verify() against MySQL doesn't work

Your code does not work because of "$password " - it has space at the end. It should be:

$query = "INSERT INTO `users` (username, password) VALUES (:username, :password)";

$params = array(
':username' => $username,
':password' => $password, // hashed one
);

Your manual test does not work because

$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";

has double quotes and it interpolates $2y, $12 and $Tz... as variables that leads to empty string. That's why single quotes works.


From your provided information I constructed sample code that does work: Check here



Related Topics



Leave a reply



Submit