Where to Put Password_Verify in Login Script

Where to put password_verify in login script?

Before you read the code, keep in mind that the Fake Registration block would not be in your code, but it is necessary to show you this, end-to-end.

<?php
session_start();
// Begin Vault
// credentials from a secure Vault, not hard-coded
$servername="localhost";
$dbname="login_system";
$username="dbUserName";
$password="dbPassword";
// End Vault

// The following two variables would come from your form, naturally
// as $_POST[]
$formEmail="jsmith123@gmail.com";
$ctPassword="¿^?fish╔&®)"; // clear text password

try {
#if(isset($_POST['email'], $_POST['password'])){
#require('../../../private_html/db_connection/connection.php');
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Begin Fake Registration
// fake it that user already had password set (from some registration insert routine)
// the registration routine had SSL/TLS, safely passing bound parameters.
$hp=password_hash($ctPassword,PASSWORD_DEFAULT); // hashed password, using
$conn->query("delete from user_accounts where email='jsmith123@gmail.com'");
$conn->query("insert user_accounts(first_name,last_name,email,password) values ('joe','smith','jsmith123@gmail.com','$hp')");
// we are done assuming we had a registration for somewhere in your system
// End Fake Registration

$query = $conn->prepare("SELECT * FROM user_accounts WHERE email=:email");
$query->bindParam(':email', $formEmail);
$query->execute();

unset($_SESSION['email']);
unset($_SESSION['first_name']);

if(($row = $query->fetch()) && (password_verify($ctPassword,$row['password']))){
$_SESSION['email'] = $row['email'];
$_SESSION['first_name'] = $row['first_name'];
//header("Location: ../../myaccount/myaccount.php");
echo "hurray, you authenticated.<br/>";
}
else {
//header("Location:../../login/login.php ");
echo "invalid login<br/>";
}
#}
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit();
}
?>

Browser Output:

hurray, you authenticated.

Note, the password_hash() function utilizes a random salt, as is evident
if you run it several times, with the hashed password changing with same clearText input, such as these hashed passwords:

$2y$10$KywNHrGiPaK9JaWvOrc8UORdT8UXe60I2Yvj86NGzdUH1uLITJv/q

$2y$10$vgJnAluvhfdwerIX3pAJ0u2UKi3J.pfvd0vIqAwL0Pjr/A0AVwatW

both of which are the result of subsequent hashings, as mentioned, of the same clear text password. The salt and hash cost are baked into the hashed password and saved. These call all be read about in links below.

From the Manual password_hash and password_verify.

Schema

create table user_accounts
( id int auto_increment primary key,
first_name varchar(50) not null,
last_name varchar(50) not null,
email varchar(100) not null,
password varchar(255) not null
);

Where to place password_verify() in php when logging in and have the registeration.php in an exernal file

You need to Select id & password without checking for password. Then you check if the pwdHash from db ($row['hashed_p']) matches the one the user gave via password_verify:

$password = // the password in it's raw form how the user typed it. like $_POST['password'];
//Check username (without password) from database
$query =
"SELECT id, hashed_p FROM `register`
WHERE `username` = '$username'";

$result = mysqli_query($database,$query);
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
$verified_password = password_verify($password, $row['hashed_p']);

if(mysqli_num_rows($result) && $verified_password){
echo 'start session succesfully';
} else {
echo 'error';
}

BUT please change to a prepared statements (because your version is very unsecure. could easily be hacked. Just seach for 'Bobby Tables'.):

$stmt = mysqli_prepare($database, $query);
mysqli_stmt_bind_param ($stmt, 's', $username);
$success = mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);

How to use password verify on the login form php

You can't use the password in the WHERE clause (so your second approach is correct), as the hash will be different for each time you use it. Furthermore, you should always select the specific number of columns you need, as you need to define each and every one of them with bind_result(). It can work with SELECT *, but then you rely on bind_result() to cover all possible values - which will break if you suddenly add another column to your table.

$stmt = $db->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();

if ($user && password_verify($_POST['password'], $user['password'])) {
$_SESSION['user_id'] = $user['id'];
header('location: indexclient.php');
exit;
} else {
echo "Invalid login";
}
$stmt->close();

Php login password_verify

<?php

$stmt = $conn->prepare("SELECT username, password FROM users WHERE username = ?");
$stmt->bind_param('s', $username);

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

$stmt->execute();
$stmt->bind_result($username, $password);
$row = $stmt->fetch(); //fetch DB results


if (!empty($row)) { // checks if the user actually exists(true/false returned)
if (password_verify($_POST['upassword'], $row['password'])) {
echo 'success'; // password_verify success!
} else {
echo 'failed';
}
} else {
echo "This user does not exist"; //email entered does not match any in DB
}

$stmt->close();
$conn->close();

You do not necessarilly need to check for number of rows. Also have an else statement if the password is not verified for any reason

Login system with password_verify()

I think I see the problem.

It looks like you're probably fetching the only row from the results before the if

$row = mysqli_fetch_assoc($result);

Then when you fetch again here, there's nothing left to fetch.

if(($result->num_rows > 0))
{
while($row = mysqli_fetch_array($result))

(I'm assuming the query will only return one row since username is unique.)

PHP can not login with correct password using password_hash()/password_verify()

I've created a simple gist where you can see a version of your code which I managed to run correctly and got the correct results:

  • a user can signup
  • a user can sign in
  • a user can sign out

I find that your code was correct, in broad strokes, but I also believe you must have mixed up some of your variables and field names.

In your question you do a var_dump of $row['pwdUsers'], a field never seen in the insert statement. You also select the field username when fetching data to compare to the one submitted for login, but in the insert statement the variable that you insert into that field is named $mailuid (while a variable $username sits next to it).

Given that when extracted and applied in a controlled environment your code works, I'd wager your error is due to a possible mix-up caused by the previously mentioned confusing nomenclatures, or due to some other logic hidden from us in the snippets you provided.



Related Topics



Leave a reply



Submit