password_verify issues

I am trying to log in using the username and password I signed up with but I just keep getting my "no user found" message so it clearly isn't working but I don't know why.

      
$password = $link->real_escape_string($_POST['password']);
		$email = $link->real_escape_string($_POST['email']);
		
		$sql = "SELECT password, userID FROM `users` WHERE email = '$email' LIMIT 1";
		$result = $link->query($sql);
		if ($result->num_rows == 1) {
		$row = $result->fetch_assoc();
		$db_password = $row["password"];
		if(password_verify($password, $db_password)) {
			
			echo "correct";
			
			} else {
			
			echo "no user found";
			}
		}

Open in new window


I used this to create my password on my register page:

$password = trim(password_hash($password, PASSWORD_BCRYPT, [12]));

Open in new window

LVL 1
Black SulfurAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Ray PaseurConnect With a Mentor Commented:
The blank screen is because the value in $secret is boolean FALSE.  PHP is not very revealing when you use echo to print information.

A good general design for a login system is given in this article:
https://www.experts-exchange.com/articles/2391/PHP-Client-Registration-Login-Logout-and-Easy-Access-Control.html

You might want to try something like this (untested, but probably close to correct).   It would let you see a password in the form it is stored in the database.
// DO NOTHING TO THIS FIELD -- IT IS NOT USED IN A QUERY
$password = $_POST['password'];

$email = $link->real_escape_string($_POST['email']);

$sql = "SELECT password, userID FROM `users` WHERE email = '$email' LIMIT 1";
$result = $link->query($sql);
if ($result->num_rows == 1) 
{
    $row = $result->fetch_assoc();
    
    // SHOW THE HASH INFORMATION FROM THE DB
    $db_password = $row['db_password'];
    var_dump($db_password);
    
    // SHOW THE HASH OF THE CLIENT INPUT PASSWORD
    $hash = password_hash($password, PASSWORD_BCRYPT, [12]);
    var_dump($hash);
    
    // COMPARE THE HASHED INFORMATION
    if ($db_password == $hash)
    {
        echo PHP_EOL . "MATCH!";
    }
    else
    {
        echo PHP_EOL . "NO MATCH!";
    }
}
else
{
    echo PHP_EOL . "$sql FOUND NOTHING";
}

Open in new window

0
 
Ray PaseurCommented:
Have you tried printing out the values in $password and $db_password and checking them manually?  If you can, please post those strings here, using the code snippet.

Also, I can't find any way to tell password_verify() about the parameters used in creating the password_hash() so it may only work with the "vanilla" hash strings.  Might be worth testing that!
0
 
Ray PaseurCommented:
Hmm... No trouble found here.  Are the character sets consistent across PHP and the database?
https://iconoun.com/demo/temp_blacksulfur.php
<?php // demo/temp_blacksulfur.php
/**
 * https://www.experts-exchange.com/questions/28966548/password-verify-issues.html
 *
 * http://php.net/manual/en/function.password-hash.php
 * http://php.net/manual/en/function.password-verify.php
 */
error_reporting(E_ALL);
echo '<pre>';


$pw = 'gooseball';
$h1 = trim(password_hash($pw, PASSWORD_BCRYPT, [12]));
$h2 = password_hash($pw, PASSWORD_DEFAULT);
var_dump($pw, $h1, $h2);

// TEST
if (password_verify($pw, $h1)) echo PHP_EOL . "$pw == $h1";
if (password_verify($pw, $h2)) echo PHP_EOL . "$pw == $h2";

Open in new window

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
Black SulfurAuthor Commented:
Still checking this out... But if I run your code in my page I get:

string(9) "gooseball"
string(60) "$2y$10$iSzAQrbKyYoSFLyc8a9ggOQbRjrgC.XGEBFAIbtKnn4cT4aDYHULi"
string(60) "$2y$10$h8ousnvYyyEKEwOYhdtKremY/GkZ/kzGIYbDS5ZGlUAi9UEJXX/Zy"

gooseball == $2y$10$iSzAQrbKyYoSFLyc8a9ggOQbRjrgC.XGEBFAIbtKnn4cT4aDYHULi
gooseball == $2y$10$h8ousnvYyyEKEwOYhdtKremY/GkZ/kzGIYbDS5ZGlUAi9UEJXX/Zy
0
 
Ray PaseurCommented:
Yes, that is what I see, too.  Seems to suggest that password_verify() can recognize either of the hash values.
0
 
Black SulfurAuthor Commented:
Man, I am getting confused now (for a change). Can I do this to test?

$secret = password_verify($password, $db_password);
echo $secret;

Open in new window


That returns a blank screen.

I am not sure where I should put the var_dump in relation to my code.
0
 
Black SulfurAuthor Commented:
Not sure if this helps in any way, but in my DB all the text columns are utf8_general_ci and my integer columns have no collation even though I selected utf8_general_ci. For some reason they just remain empty.
0
 
Black SulfurAuthor Commented:
I tried mine with your example and I just get a blank screen as well.

$password = $link->real_escape_string($_POST['password']);
		$email = $link->real_escape_string($_POST['email']);
		
		$sql = "SELECT password, userID FROM `users` WHERE email = '$email' LIMIT 1";
		$result = $link->query($sql);
		if ($result->num_rows == 1) {
		$row = $result->fetch_assoc();
		$db_password = $row["password"];
			if(password_verify($password, $db_password)) echo PHP_EOL . "$password == $db_password";
			

Open in new window

0
 
Black SulfurAuthor Commented:
Thanks, Ray. I will check that out but I really want to get this to work. I have incorporated your code into mine and it doesn't show a match.

I actually deleted all my data from the database and signed up again using the password "test". Then I tried to login and result is:

string(60) "$2y$10$fwmftAXT/C74/qZrKj488eBbr87Xv9U4fcmX2HfOvgFV1vtTO.PTG"
string(60) "$2y$10$ePzFcO/leSiao2wX8WFrRezgw8wVIXx5Id6FSEOxMWiJQU66EqYt."

I just don't understand why this is. It's driving me crazy!
0
 
Black SulfurAuthor Commented:
Just to double check.. Here is the code above this. Not sure if it might be interfering in any way?

$error = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	
	
	if (!$_POST['email']) {
		
		$error .= "Email required <br>";
	}
	
	if ($_POST['email'] && filter_var($_POST["email"], FILTER_VALIDATE_EMAIL) === false) {

            $error .= "The email address is invalid.<br>";

        }
	
	if (!$_POST['password']) {
		
		$error .= "Password required";
		
	} else {
		
		$password = $_POST['password'];
		$email = $link->real_escape_string($_POST['email']);
		
		$sql = "SELECT password, userID FROM `users` WHERE email = '$email' LIMIT 1";
		$result = $link->query($sql);
		if ($result->num_rows == 1) {
		$row = $result->fetch_assoc();
                //rest of code here

Open in new window

0
 
Black SulfurAuthor Commented:
And one last thing. Here is my insert code for the register page. It might have something to do with it or not. Worth posting though.

$stmt = $link->prepare("INSERT INTO `users` (email, password, firstName, identifier) VALUES (?, ?, ?, ?)");
			$stmt->bind_param("ssss", $email, $password, $name, $identifier);
			$email = htmlentities($_POST['email'], ENT_QUOTES);
			$password = trim(password_hash($password, PASSWORD_BCRYPT, [12]));
			$name = htmlspecialchars($_POST['name']);
			$identifier = bin2hex($identifier);
			$stmt->execute();
			$stmt->close();

Open in new window

0
 
Black SulfurAuthor Commented:
I figured it out!!!!!!

It was the one line in my register page code.

I changed this:

$password = trim(password_hash($password, PASSWORD_BCRYPT, [12]));

Open in new window


to this:

$password = trim(password_hash($_POST['password'], PASSWORD_BCRYPT, [12]));

Open in new window


Man, Oh man was that painful. Can I give myself points?? :P
0
 
Ray PaseurCommented:
OK, it looks like string comparison is inadequate for dealing with these hashed passwords; the same password will not always hash into the same output string.  We must use the related PHP functions to compare the values.  Try these three links:
https://iconoun.com/demo/temp_blacksulfur.php?q=secret <-- This one works.
https://iconoun.com/demo/temp_blacksulfur.php?q=foo
https://iconoun.com/demo/temp_blacksulfur.php

Here is the test script.
<?php // demo/temp_blacksulfur.php
/**
 * https://www.experts-exchange.com/questions/28966548/password-verify-issues.html
 *
 * READ THE USER-CONTRIBUTED NOTES CAREFULLY!
 * http://php.net/manual/en/function.password-hash.php
 * http://php.net/manual/en/function.password-verify.php
 *
 * References for PHP and MySQL(i):
 *
 * http://php.net/manual/en/mysqli.overview.php
 * http://php.net/manual/en/class.mysqli.php
 * http://php.net/manual/en/class.mysqli-stmt.php
 * http://php.net/manual/en/class.mysqli-result.php
 * http://php.net/manual/en/class.mysqli-warning.php
 * http://php.net/manual/en/class.mysqli-sql-exception.php <-- DID NOT WORK PHP 5.3+, MySQL 5.1+
 *
 * http://php.net/manual/en/mysqli.construct.php
 * http://php.net/manual/en/mysqli.real-escape-string.php
 * http://php.net/manual/en/mysqli.query.php
 * http://php.net/manual/en/mysqli.errno.php
 * http://php.net/manual/en/mysqli.error.php
 * http://php.net/manual/en/mysqli.insert-id.php
 *
 * http://php.net/manual/en/mysqli-result.num-rows.php
 * http://php.net/manual/en/mysqli-result.fetch-array.php <-- DO NOT USE THIS
 * http://php.net/manual/en/mysqli-result.fetch-object.php
 */
ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo '<pre>';


// TEST AGAINST THIS PASSWORD
$vwd = 'secret';


// DATABASE CONNECTION AND SELECTION VARIABLES - GET THESE FROM YOUR HOSTING COMPANY
$db_host = "localhost"; // PROBABLY THIS IS OK
$db_name = "??";
$db_user = "??";
$db_word = "??";
require_once('RAY_live_data.php');
// OPEN A CONNECTION TO THE DATA BASE SERVER AND SELECT THE DB
$mysqli = new mysqli($db_host, $db_user, $db_word, $db_name);

// DID THE CONNECT/SELECT WORK OR FAIL?
if ($mysqli->connect_errno)
{
    $err
    = "CONNECT FAIL: "
    . $mysqli->connect_errno
    . ' '
    . $mysqli->connect_error
    ;
    trigger_error($err, E_USER_ERROR);
}

// ACTIVATE THIS TO SHOW WHAT THE DB CONNECTION OBJECT LOOKS LIKE
// var_dump($mysqli);


// CREATING A TABLE FOR OUR TEST DATA
$sql
=
"
CREATE TEMPORARY TABLE my_table
( id    INT          NOT NULL AUTO_INCREMENT PRIMARY KEY
, pwd   VARCHAR(255) NOT NULL DEFAULT ''
, xwhen TIMESTAMP    NOT NULL
)
"
;

// IF mysqli::query() RETURNS FALSE, LOG AND SHOW THE ERROR
if (!$res = $mysqli->query($sql))
{
    $err
    = 'QUERY FAILURE:'
    . ' ERRNO: '
    . $mysqli->errno
    . ' ERROR: '
    . $mysqli->error
    . ' QUERY: '
    . $sql
    ;
    trigger_error($err, E_USER_ERROR);
}

// ACTIVATE THIS TO SHOW THE RESULTS OF THE QUERY
// var_dump($res);


// LOADING OUR VERIFICATION DATA INTO THE TABLE
$pwd = password_hash($vwd, PASSWORD_DEFAULT);
$pwd = $mysqli->real_escape_string($pwd);
$sql = "INSERT INTO my_table ( pwd ) VALUES ( '$pwd' )";
$res = $mysqli->query($sql);
if (!$res)
{
    $err
    = 'QUERY FAILURE:'
    . ' ERRNO: '
    . $mysqli->errno
    . ' ERROR: '
    . $mysqli->error
    . ' QUERY: '
    . $sql
    ;
    trigger_error($err, E_USER_ERROR);
}

// ACTIVATE THIS TO SHOW THE QUERY
// echo PHP_EOL . $sql;


// INTERPRET THE URL ARGUMENT AND TRY THE QUERY
$arg = !empty($_GET['q']) ? $_GET['q'] : 'Missing "q=" URL parameter';

$sql = "SELECT id, pwd FROM my_table WHERE id=1 LIMIT 1";
$res = $mysqli->query($sql);
$num = $res->num_rows;
if ($num)
{
    $row = $res->fetch_object();
    if (password_verify($arg, $row->pwd))
    {
        echo PHP_EOL . "Found PW match for <b>$arg</b> in row with id=$row->id";
    }
    else
    {
        echo PHP_EOL . "Found no PW match for <b>$arg</b>";
    }
}

Open in new window

HTH, ~Ray
0
 
Ray PaseurCommented:
Regarding this:
https://www.experts-exchange.com/questions/28966548/password-verify-issues.html#a41777011

I thought you already had assigned $password with this:
$password = $_POST['password'];

But if your script had not made that assignment, you would have gotten a Notice when your script tried to use an undefined variable.

Check AntiPractice #4 here to learn how to visualize undefined variables!
https://www.experts-exchange.com/articles/12293/AntiPHPatterns-and-AntiPHPractices.html

Seriously, you might want to have a look at this article, too.  It contains tested and working code samples you can copy and install right now.
https://www.experts-exchange.com/articles/2391/PHP-Client-Registration-Login-Logout-and-Easy-Access-Control.html

Then once you have that much working, you can go back in and do things like refactor the md5() into hashed passwords instead.
0
 
Black SulfurAuthor Commented:
Thanks, Ray. Yes, I checked out your link to a full solution for client registration, login and logout ( I do intend to use this in future)  which I could just copy and paste but I am trying to do it from scratch on my own to try help me learn and understand better. Unfortunately I get stuck ( a lot) but at least I learn something when I get stuck and really helpful people like you come along and help me out! :)

It would seem I have another problem now which I will ask in a related question.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.