Password_verify() returning False with correct password

I am trying to build a simple user registration/login system, the registration form is functional enough for the time being, it works, but when I attempt to login using the username/password which are correct, my login.php script breaks when it runs the password_verify method. I am fairly new to web development, and have done a few days worth of googling / article reading before coming here. Here is the code

<?php

session_start();

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

	include 'dbh.php';

	$uid = mysqli_real_escape_string($conn, $_POST['uid']);
	$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);

	//Error handlers
	//Check if inputs are empty
	if (empty($uid) || empty($pwd)) {
		header("Location: index.html?login=error");
		exit();
	} else { 
		$sql = "SELECT * FROM user WHERE uid='$uid'";
		$result = mysqli_query($conn, $sql);
		$resultCheck = mysqli_num_rows($result);
		if ($resultCheck < 1) {
			header("Location: index.html?login=error");
			exit();
		} else {
			if ($row = mysqli_fetch_assoc($result)) {
				


				//De-hashing the password 
				//something goes wronge here!!!!!!!!! 
				$hashedPwdCheck = password_verify($pwd, $row['pwd']);
				if ($hashedPwdCheck == false) {
					header("Location: index.html?login=error");
					exit();
					//BREAKPOINT!!!!



				} elseif ($hashedPwdCheck == true) {
					//Login the user here
					$_SESSION['user_id'] = $row['user_id'];
					$_SESSION['uid'] = $row['uid'];
					$_SESSION['pwd'] = $row['pwd'];
					header("Location: index.html?login=success");
					exit();
				}
			}
		}
	}

	$sql = "SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'";
	$result = $conn->query($sql);

	if (!$row = $result->fetch_assoc()) {
		echo "username or password incorrect";
	} else {
		echo "login successful";
	}

} else {
	header("Location: index.html?login=error");
	exit();
}


?>

also here is a screenshot of the user table on phpmyadmin

Any help would be greatly appreciated!

What exactly does ā€œscript breaksā€ mean? Do you have error reporting turned on? What is the error message?

You need to use Prepared Statements. NEVER EVER put variables in a query
You need to check the Request Method not depend on the name of a button being submitted in order for the script to work.

How do you expect to use GET parameters on pages with a .html extension?

Do not SELECT *. Specify the column names you want

You do not need to explicitly check for true or false on the password check. The if statement already does that.

The last query is going to always fail.

Since you are just learning, I suggest you use PDO. Here is a tutorial to get you going. https://phpdelusions.net/pdo

1 Like

this may sound barbaric, but I basically changed the
header("Location: index.html?login=error");
to
header("Location: index.hl?login=error");
resulting in a ā€œPage Not Foundā€ error wherever an error could occur in the login.php script, then tested each breakpoint until I isolated the error in the password_verify method. Again, fairly new to web development, Iā€™m sure thereā€™s a better way to do that, but Iā€™m kinda learning as I go here.

1 Like

You can simplify checking for password by removing unnecessary code

if (password_verify($pwd, $row['pwd'])) {
	//Login the user here
	$_SESSION['user_id'] = $row['user_id'];
	$_SESSION['uid'] = $row['uid'];
	$_SESSION['pwd'] = $row['pwd'];
	header("Location: index.html?login=success");
	exit();
} else {
	header("Location: index.html?login=error");
	exit();
}
1 Like

The basics of debugging include verifying that your code has reached a certain point and that your variables contain the expected values. So try this:

//De-hashing the password 
//something goes wrong here!!!!!!!!!
$pwdHashed = password_hash($pwd);
echo "Raw Password {$pwd}<br>";
echo "Hashed Password {$pwdHashed}<br>";
echo "Stored Password {$row['pwd']}<br>";
die('testing password');

And analyze the results.

I missed it earlier. DO NOT put the password in a session. Not now, not ever.

Is your pwd column large enough to store the hashed password? I canā€™t see the length on the screen shot.

I know the discussion has been focusing on the password. But Iā€™m interested in knowing what the difference is between user_id int(11) and uid text. It just doesnā€™t feel right to me somehow.

I believe text data types are larger than varchar so I donā€™t really think itā€™s a matter of data types. But a matter of logic flaws.

Whatā€™s this last bit? Is it an older version that you forgot to delete?

Hence my postā€¦

1 Like

Sorry for the delayed response all, I manged to dial this puppy in over the week. Here is the header.php it contains modal forms for both signup and login. Both working

<?php
  session_start();
?>

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>beatzz</title>
    <link rel="icon" type="image/vnd.microsoft.icon" href="img/favicon.ico" />
                      <!-- metadata -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
                      <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
                      <!-- jQuery JavaScript -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
                      <!-- Bootstrap core JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
                      <!-- HTML5 shiv -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
                      <!-- Bootstrap overrides -->
    <link rel="stylesheet" type="text/css" href="css/styles.css">
  </head>

  <body>
    <div class="wrapper">
                      <!-- navbar -->
      <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container-fluid">
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#myNavbar" aria-expanded="false" aria-controls="navbar">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar top-bar"></span>
              <span class="icon-bar middle-bar"></span>
              <span class="icon-bar bottom-bar"></span>
            </button>
            <img id="sheep" src="img/sheep.png">
          </div>
          <div class="collapse navbar-collapse" id="myNavbar">
            <ul class="nav navbar-nav">
              <li><a href="index.php">Updates</a></li>
              <li><a href="projects.php">Projects</a></li>
              <li><a href="docs.php">Documentation</a></li>
              <li><a href="links.php">links</a></li>
              <li><a href="contact.php">Contact</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">

              <?php
                if (isset($_SESSION['user_uid'])) {
                  echo '<li><a href="includes/logout.inc.php"><span class="glyphicon glyphicon-log-in"></span> Logout</a></li>';
                } else {
                  echo "<li><a onclick=\"document.getElementById('signup').style.display='block'\"><span  class=\"glyphicon glyphicon-user\"></span>Signup</a></li>";
                  echo "<li><a onclick=\"document.getElementById('login').style.display='block'\"><span class=\"glyphicon glyphicon-log-in\"></span>Login</a></li>";
                }
              ?>

            </ul>
          </div>
        </div>
      </nav>

                <!-- The Login Modal -->
      <div id="login" class="modal">
        <span onclick="document.getElementById('login').style.display='none'"
          class="close" title="Close Modal">&times;</span>

        <form class="login-modal-content animate" action="includes/login.inc.php" method="POST">
          <div class="imgcontainer">
            <img id="blacksheep" src="img/blacksheep.png" alt="Avatar" class="avatar">
          </div>

          <div class="container">
            <label><b>Username</b></label>
            <input name="uid" class="form-control" id="uid" type="text" placeholder="Userame" 
              required data-validation-required-message="Please enter your username.">
            <p class="help-block text-danger"></p>

            <label><b>Password</b></label>
            <input name="pwd" class="form-control" id="pwd" type="password" placeholder="Password" 
              required data-validation-required-message="Please enter your password.">
            <p class="help-block text-danger"></p>

            <button type="submit" name="loginbtn" class="loginbtn">Login</button>
            <input type="checkbox" checked="checked"> Remember me
          </div>

          <div class="container">
            <button type="button" onclick="document.getElementById('login').style.display='none'" class="cancelbtn">Cancel</button>
            <span class="psw">Forgot <a href="#">password?</a></span>
          </div>
        </form>
      </div>

            <!-- The Signup Modal -->
      <div id="signup" class="modal">
        <span onclick="document.getElementById('signup').style.display='none'" class="signup-close" title="Close Modal">&times;</span>
        <form class="signup-modal-content animate" action="includes/signup.inc.php">
          <div class="imgcontainer">
            <img id="blacksheep" src="img/blacksheep.png" alt="Avatar" class="avatar">
          </div>
          <div class="container">
            <label><b>First Name</b></label>
            <input name="first" class="form-control" id="first" type="text" placeholder="first name"
              required data-validation-required-message="Please enter your first name.">
            <p class="help-block text-danger"></p>

            <label><b>Last Name</b></label>
            <input name="last" class="form-control" id="last" type="text" placeholder="last name"
              required data-validation-required-message="Please enter your last name.">
            <p class="help-block text-danger"></p>

            <label><b>Email Address</b></label>
            <input name="email" class="form-control" id="email" type="text" placeholder="email@address.com"
              required data-validation-required-message="Please enter your email address.">
            <p class="help-block text-danger"></p>

            <label><b>Username</b></label>
            <input name="uid" class="form-control" id="uid" type="text" placeholder="username"
              required data-validation-required-message="Please enter desired username.">
            <p class="help-block text-danger"></p>

            <label><b>Password</b></label>
            <input name="pwd" class="form-control" id="pwd" type="password" placeholder="password"
              required data-validation-required-message="Please enter your password.">
            <p class="help-block text-danger"></p>

            <label><b>Repeat Password</b></label>
            <input name="pwd-repeat" class="form-control" id="pwd-repeat" type="password" placeholder="repeat password"
              required data-validation-required-message="Please re-enter your password.">
            <p class="help-block text-danger"></p>

            <input type="checkbox" checked="checked"> Remember me

            <p>By creating an account you agree to our <a href="privacy.php">Terms & Privacy</a>.</p>

            <div class="clearfix">
              <button type="button" onclick="document.getElementById('signup').style.display='none'" class="cancelbtn">Cancel</button>
              <button type="submit" class="signupbtn">Sign Up</button>
            </div>
          </div>
        </form>
      </div>

      <script>
        // Get the modal
        var login = document.getElementById('login');
        var signup = document.getElementById('signup');

        // When the user clicks anywhere outside of the modal, close it
        window.onclick = function(event) {
            if (event.target == login) {
                modal.style.display = "none";
            } elseif (event.target == signup) {
                modal.style.display = "none";
            }
        }
      </script>


And the signup.inc.php

<?php

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

		include_once 'dbh.inc.php';

		$first = mysqli_real_escape_string($conn, $_POST['first']);
		$last = mysqli_real_escape_string($conn, $_POST['last']);
		$email = mysqli_real_escape_string($conn, $_POST['email']);
		$uid = mysqli_real_escape_string($conn, $_POST['uid']);
		$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);

		//Error handlers

		//Check for empty fields
		if (empty($first) || empty($last) || empty($email) || empty($uid) || empty($pwd)) {

			header("Location: ../signup.php?signup=empty");
			exit();

		} else {

			//Check if input characters are valid
			if (!preg_match("/^[a-zA-Z]*$/", $first) || !preg_match("/^[a-zA-Z]*$/", $last)) {

				header("Location: ../signup.php?signup=invalid");
				exit();

			} else {

				//Check if email is valid
				if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

					header("Location: ../signup.php?signup=email");
					exit();

				} else {

					//Check if username is available
					$sql = "SELECT * FROM users WHERE user_uid='$uid'";
					$result = mysqli_query($conn, $sql);
					$resultCheck = mysqli_num_rows($result);

					if ($resultCheck > 0) {

						header("Location: ../signup.php?signup=usertaken");
						exit();

					} else {

						//Hashing the password
						$hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);

						//Insert the user into database
						$sql = "INSERT INTO users (user_first, user_last, user_email, user_uid, user_pwd) VALUES ('$first', '$last', '$email', '$uid', '$hashedPwd')";

						mysqli_query($conn, $sql);

						header("Location: ../index.php?signup=success");
						exit();

					}

				}

			}

		}

	} else {

		header("Location: ../signup.php");
		exit();

	}

?>

and finally the login.inc.php

<?php

	session_start();

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

		include_once 'dbh.inc.php';

		$uid = mysqli_real_escape_string($conn, $_POST['uid']);
		$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);

		//Error handlers

		//Check if inputs are empty
		if (empty($uid) || empty($pwd)) {

			header("Location: ../index.php?login=error_empty");
			exit();

		} else { 

			//Check if username is in database
			$sql = "SELECT * FROM users WHERE user_uid='$uid'";
			$result = mysqli_query($conn, $sql);
			$resultCheck = mysqli_num_rows($result);

			if ($resultCheck < 1) {

				header("Location: ../index.php?login=error_notfound");
				exit();

			} else {

				//Check if password is correct
				if ($row = mysqli_fetch_assoc($result)) {

					//De-hashing the password 
					$hashedPwdCheck = password_verify($pwd, $row['user_pwd']);

					if ($hashedPwdCheck == false) {

						header("Location: ../index.php?login=error");
						exit();

					} elseif ($hashedPwdCheck == true) {

						//Login the user here
						$_SESSION['user_id'] = $row['user_id'];
						$_SESSION['user_first'] = $row['user_first'];
						$_SESSION['user_last'] = $row['user_last'];
						$_SESSION['user_email'] = $row['user_email'];
						$_SESSION['user_uid'] = $row['user_uid'];

						header("Location: ../updates.php?login=success");
						exit();

					}

				}

			}

		}


	} else {

		header("Location: ../index.php?login=error");
		exit();

	}

?>

Glad to see you got it working. Now switch to PDO and prepared statements you might have a usable solution. And maybe clean up some of the unnecessary if else combos.

2 Likes

Yeah, you need to put on your big boy pants and use PDO with Prepared Statements. The code may ā€œworkā€ but it still has a handful of changes needed besides PDO.

1 Like

likeā€¦ this!!!

dbh.inc.php

<?php

$servername = "localhost";
$username = "root";
$password = "********";
$database = "login";

try {

	$conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
	$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

}

catch(PDOException $e) {

	$conn = null;
	echo "Connection failed: " . $e->getMessage();

}

?>

signup.inc.php

<?php

session_start();

  // check whether the signupbtn was clicked
if (isset($_POST['signupbtn'])) {

	include_once 'dbh.inc.php';

		// initialize variable
	$first = $_POST['first'];
	$last = $_POST['last'];
	$email = $_POST['email'];
	$uid = $_POST['uid'];
	$pwd = $_POST['pwd'];
	$pwdRepeat = $_POST['pwd-repeat'];

		// error handlers

		// check for empty fields
	if (empty($first) || empty($last) || empty($email) || empty($uid) || empty($pwd)) {

		$conn = null;
		header("Location: ../signup.php?signup=error_field");
		exit();

	} else {

			// check if input characters are valid
		if (!preg_match("/^[a-zA-Z]*$/", $first) || !preg_match("/^[a-zA-Z]*$/", $last)) {

			$conn = null;
			header("Location: ../signup.php?signup=error_name");
			exit();

		} else {

				// check if email is valid
			if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

				$conn = null;
				header("Location: ../signup.php?signup=error_email");
				exit();

			} else {

					// check if username is available
				$stmt = $conn->prepare("SELECT * FROM users WHERE user_uid = ?");
				$stmt->execute([$uid]);
				if ($stmt->rowCount() > 0) {

					$conn = null;
					header("Location: ../signup.php?login=error_unavailable");
					exit();

				} else {

				    	// check if the password was validated by the user
					if (!pwdRepeat == pwd) {

						$conn = null;
						header("Location: ../signup.php?signup=error_passwords");
						exit();

					} else {
						
							// hashing the password
						$hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);

							// insert the user into database
						$sql = "INSERT INTO users (user_first, user_last, user_email, user_uid, user_pwd) VALUES (?,?,?,?,?)";
						$conn->prepare($sql)->execute([$first, $last, $email, $uid, $hashedPwd]);

							// login the user in
						$stmt = $conn->prepare("SELECT user_id, user_first, user_last, user_email, user_uid FROM users WHERE user_uid = ?");
						$stmt->execute([$uid]);
						$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

						$_SESSION['user_id'] = $result[0]['user_id'];
						$_SESSION['user_first'] = $result[0]['user_first'];
						$_SESSION['user_last'] = $result[0]['user_last'];
						$_SESSION['user_email'] = $result[0]['user_email'];
						$_SESSION['user_uid'] = $result[0]['user_uid'];

						$conn = null;
						header("Location: ../updates.php?login=success");
						exit();

					}	

				}

			}

		}

	}

} else {

	header("Location: ../signup.php?signup=error");
	exit();

}

?>

login.inc.php

<?php

session_start();

  // check whether the loginbtn was clicked
if (isset($_POST['loginbtn'])) {

  include_once 'dbh.inc.php';

    // initialize variable
  $uid = $_POST['uid'];
  $pwd = $_POST['pwd'];

    // error handlers

    // check if inputs are empty
  if (empty($uid) || empty($pwd)) {

    $conn = null;
    header("Location: ../index.php?login=error_field");
    exit();

  } else {

      // check if username is in database
    $stmt = $conn->prepare("SELECT user_uid FROM users WHERE user_uid = ?");
    $stmt->execute([$uid]);

    if ($stmt->rowCount() < 1) {

      $conn = null;
      header("Location: ../index.php?login=error_username");
      exit();

    } else {

        // check if password is correct
      $stmt = $conn->prepare("SELECT user_pwd FROM users WHERE user_uid = ?");
      $stmt->execute([$uid]);
      $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // dehashing the password
      $hashedPwdCheck = password_verify($pwd, $result[0]['user_pwd']);

      if ($hashedPwdCheck == false) {

        $conn = null;
        header("Location: ../index.php?login=error_password");
        exit();

      } else {

          // login the user in
        $stmt = $conn->prepare("SELECT user_id, user_first, user_last, user_email, user_uid FROM users WHERE user_uid = ?");
        $stmt->execute([$uid]);
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $_SESSION['user_id'] = $result[0]['user_id'];
        $_SESSION['user_first'] = $result[0]['user_first'];
        $_SESSION['user_last'] = $result[0]['user_last'];
        $_SESSION['user_email'] = $result[0]['user_email'];
        $_SESSION['user_uid'] = $result[0]['user_uid'];

        $conn = null;
        header("Location: ../updates.php?login=success");
        exit();

      }

    }

  }

} else {

  header("Location: ../index.php?login=error");
  exit();

}

?>

Previously I have found that leading and trailing spaces often cause a problem and can be eliminated by using PHP trim(ā€¦) where appropriate.

2 Likes

Good job on switching to PDO. There is still quite a bit to do to clean up the code though. Probably easier to just show you an example of what to do now. Study the code in my repository and see what you can learn from it. https://github.com/benanamen/perfect_app

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