'Email/Username combination is incorrect error in login system

I have a login system on my website where someone can create an account, then logout and then log back in. A message displays when a user tries to log into an account that doesn't exist. "Email/Username combination is incorrect". The problem I am having is that this message is displaying even when the account does exist.

Here is index.php

<!DOCTYPE html>
<?php

session_start();

if(isset($_SESSION['username'])) {

header("Location: home.php");

$_SESSION["success"] = "You are now logged in";

}


?>
<html>

<head>


</head>


<body>

<form action="verify_registration_form.php" method="post">
<br>
<input type="username" id="user_name" name="user_name" placeholder="Username" required>
<br><br><br><br><input type="password" id="user_pass_word" name="user_pass_word" placeholder="Password" required>
<br><br><br><br><input type="email" id="user_email" name="user_email" placeholder="Email" required>
<br><br><br><br><input type="submit" class="submit_registration_form_button" id="submit_registration_form_button" name="submit_registration_form_button" value="Sign Up">

</form>

<form action="verify_login_form.php" method="post">

<input type="username" id="user_email_login" name="user_email_login" placeholder="Email" required>
<input type="password" id="user_pass_word_login" name="user_pass_word_login" placeholder="Password" required>
<input type="submit" class="submit_user_login_form_button" id="submit_user_login_form_button" name="submit_registration_form_button" value="Log In">

</form>


</body>


</html>

Here is home.php

<!DOCTYPE html>
<?php

session_start();

if(!isset($_SESSION['username'])) {


header('Location: index.php');

}



?>
<html>

<head>


</head>


<body>

<?php

echo $_SESSION["success"];


?>

<?php if (isset($_SESSION['username'])) : ?>

<p>Welcome <?php echo $_SESSION['username']; ?>


<br><br>

<form action="logout.php" method="post">
<input type="submit" id="logoutbutton" name="logoutbutton" class="logoutbutton" value="Logout">
</form>

<?php  endif ?>

</body>


</html>

Here is verify_login_form.php

<!DOCTYPE html>
<?php

session_start();


if($_SERVER['REQUEST_METHOD'] != 'POST') {

header("Location: index.php");

}else{

$connection = mysqli_connect("localhost", "root", "", "websiteusers");

if(!$connection) {

echo "Could not connect to MYSQL database";

}else{
echo "Sucessfully connected to MYSQL database";
$connection = mysqli_connect("localhost", "root", "", "websiteusers");
$useremail = mysqli_real_escape_string($connection, 
$_POST["user_email_login"]);
$userpassword = mysqli_real_escape_string($connection, 
$_POST["user_pass_word_login"]);
$query = "SELECT * FROM websiteusers WHERE UserEmail='$useremail' AND UserPassWord='$hasheduserpassword'";
$results = mysqli_query($connection, $query);
if(mysqli_num_rows($results) == 1) {

$_SESSION['username'] = $username;
$_SESSION['success'] = "You are now logged in";
header("Location: home.php");
}else{

echo "Email/Username combination is incorrect";

}



}

}




?>
<html>

<head>


</head>

<body>



</body>



</html>


Solution 1:[1]

You can't compare hashed passwords directly. You need to use password_verify instead. Change your code to something like:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli("localhost", "root", "", "websiteusers");
$db->set_charset("utf8mb4");

$query = "SELECT * FROM websiteusers WHERE UserEmail=?";
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $_POST["user_email_login"]);
$stmt->execute();
$row = $stmt->get_result()->fetch_assoc();
if($row && password_verify($_POST["user_pass_word_login"], $row['UserPassWord'])) {

The reason for this is that password_hash() is using a random salt to enhance the hash security, and the generated hash contains this salt. password_verify() extracts the salt from this hash, and hashes your compared string with the same salt, resulting (if the two passwords are the same) in the same hash, whereas using password_hash() a second time results in a different random salt used, which won't generate the same hash, and thus the compare will fail (thanks @Aurelien for this explanation).

Note that mysqli_real_escape_string is not intended for protecting from SQL injection, and if used for this purpose some day will fail you. You should use prepared statements instead.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Your Common Sense