0

I've been developing a secure login page for users but somehow the password verification seems not to work when logging in.

The code below seems to locate the username in the database I've created in MySql, but mainly the password doesn't match every time.

I've made all possible changes, tried all advices but still, no success. If anyone has any solutions for this issue it would be greatly appreciated.

Error always displays that the password is not the right one.

Login Page:

<?php
/* User login process, checks if user exists and password is correct */

// Escape email to protect against SQL injections
$username = $mysqli->escape_string($_POST['username']);
$password = $mysqli->escape_string(password_hash($_POST['password'], PASSWORD_BCRYPT));
$result = $mysqli->query("SELECT * FROM `users` WHERE `username`='$username'");

if ( $result->num_rows == 0 ){ // User doesn't exist
    $_SESSION['message'] = "User with that username doesn't exist!";
    header("location: error.php");
}
else { // User exists
    $user = $result->fetch_assoc();

    if ( password_verify($_POST['password'], $user['password']) ) {

        $_SESSION['email'] = $user['email'];
        $_SESSION['first_name'] = $user['first_name'];
        $_SESSION['last_name'] = $user['last_name'];
        $_SESSION['username'] = $user['username'];
        $_SESSION['active'] = $user['active'];

        // This is how we'll know the user is logged in
        $_SESSION['logged_in'] = true;

        header("location: dashboard.html");
    }
    else {
        $_SESSION['message'] = "You have entered wrong password, try again!";
        header("location: error.php");
    }
}

Registration Page:

<?php
/* Registration process, inserts user info into the database 
   and sends account confirmation email message
 */

// Set session variables to be used on profile.php page
$_SESSION['email'] = $_POST['email'];
$_SESSION['first_name'] = $_POST['firstname'];
$_SESSION['last_name'] = $_POST['lastname'];

// Escape all $_POST variables to protect against SQL injections
$first_name = $mysqli->escape_string($_POST['firstname']);
$last_name = $mysqli->escape_string($_POST['lastname']);
$email = $mysqli->escape_string($_POST['email']);
$password = $mysqli->escape_string(password_hash($_POST['password'], PASSWORD_BCRYPT));
$hash = $mysqli->escape_string( md5( rand(0,1000) ) );

// Check if user with that email already exists
$result = $mysqli->query("SELECT * FROM users WHERE email='$email'") or die($mysqli->error());

// We know user email exists if the rows returned are more than 0
if ( $result->num_rows > 0 ) {

    $_SESSION['message'] = 'User with this email already exists!';
    header("location: error.php");

}
else { // Email doesn't already exist in a database, proceed...

    // active is 0 by DEFAULT (no need to include it here)
    $sql = "INSERT INTO users (first_name, last_name, email, password, hash, active) " 
            . "VALUES ('$first_name','$last_name','$email','$password', '$hash', 1)";

    // Add user to the database
    if ( $mysqli->query($sql) ){

        $_SESSION['active'] = 0; //0 until user activates their account with verify.php
        $_SESSION['logged_in'] = true; // So we know the user has logged in
        $_SESSION['message'] =

                 "Confirmation link has been sent to $email, please verify
                 your account by clicking on the link in the message!";

        header("location: profile.html"); 

    }
    else {
        $_SESSION['message'] = 'Registration failed!';
        header("location: error.php");
    }
}

Here's the login/signup form the user utilizes to sign in into the system: "http://riselamagana.byethost4.com/projects/webdev3/production/index.php"

and the database would be: table "users"

The password hash that was generated for "password_28" was: " $2y$10$W3bOAG0BP/DExr/qpiT0ueVS3YHb2NVeSC3.oMAaVQbHlodJVudK.".

It still gives me the error that the password isn't correct, my guess is that the password when compared don't match, but I'm not sure why.

Any further suggestions would surely be appreciated.

  • 1
    I suggest echoing first the entered values by the user and the result of the query, just to make sure that you are receiving the values that you are expecting to – Carl Binalla May 16 '18 at 04:20
  • Can you show us the registration page on how you insert the password? because if you read the docs. The saved password needs to be hashed. – hungrykoala May 16 '18 at 04:52
  • Was the password hash stored in the database for the user generated with the password_hash() function? – SpacePhoenix May 16 '18 at 05:14
  • 1
    You need to use [password_verify](http://php.net/manual/en/function.password-verify.php). Look at [this question](https://stackoverflow.com/questions/30279321/how-to-use-password-hash) for more details – Vatev May 16 '18 at 07:15
  • For the person who asked to see the registration page, you can go to "http://riselamagana.byethost4.com/projects/webdev3/production/index.php#signup" – Luciano Peña May 16 '18 at 15:45
  • yes, the password_hash() function did store the password into the database but when called back up again and compared, they seem to not match – Luciano Peña May 16 '18 at 16:09
  • @Swellar, to respond to your suggestion, I did echo the password the user typed to login in the error.php page, the password inserted was " password_28 " but when compared to the hash is doesn't work. Any clues or further suggestions? – Luciano Peña May 16 '18 at 16:11
  • @LucianoPeña, I've edited your question to include the content from your answer; unlike a forum where you'd clarify with multiple posts, it's better to [edit](https://stackoverflow.com/posts/50362351/edit) a question to include additional information. – Chris Forrence May 16 '18 at 16:19
  • @ChrisForrence, thank you for your assistance. Kinda new to Stack Overflow community posts that's why. Sorry if the multiple posts may have confused you. – Luciano Peña May 16 '18 at 16:28
  • By the way, this isn't encryption, it's [password hashing](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded#passwords). (Using precise terminology matters with cryptography; it gets confusing enough with precise terminology, adding ambiguity just makes it even less accessible.) – Scott Arciszewski Sep 11 '18 at 20:17

2 Answers2

1

The password hash that was generated for "password_28" was: " $2y$10$W3bOAG0BP/DExr/qpiT0ueVS3YHb2NVeSC3.oMAaVQbHlodJVudK.".

Story checks out.

It still gives me the error that the password isn't correct, my guess is that the password when compared don't match, but I'm not sure why.

// ...
     $user = $result->fetch_assoc();
// ...
     if ( password_verify($_POST['password'], $user['password']) ) {
// ...

Are multiple rows being returned for $result? Is it possible that you're comparing the wrong hash in this location?

To troubleshoot this, hard-code $_POST['password'] to be "password_28" and see if it still fails. Then revert your change and hard-code your password hash. Does it still fail?

If it fails the first time, you're probably altering $_POST somewhere else in your application and that's causing the validation to fail.

If it fails the second time, first check that you're only getting one row back (otherwise, this is a trivial fix: make sure you use the correct password hahs for the correct user). If you are, you're probably running into an encoding issue with how your password hashes are being stored. Is the database column too short for the password hash? (Generally you want varchar(255) or TEXT for MySQL, since MySQL truncates by default unless you're running in strict mode.)

Finally, I'd like to recommend not using $mysqli->escape_string() and instead adopting prepared statements. Prepared statements are a much more robust strategy for preventing SQL injection in PHP software than escaping.

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
-1

You're not comparing to the hashed password, you're comparing the raw post password...

//In your code, line 6, you hash the password

$password = $mysqli->escape_string(password_hash($_POST['password'], PASSWORD_BCRYPT));

//On line 16 you don't

if ( password_verify($_POST['password'], $user['password']) ) {

//So try this instead...

if ( password_verify($password, $user['password']) ) {

Tolli
  • 21
  • 4
  • 1
    That's how `password_verify()` works. You compare the plain text to the hashed value. – miken32 Dec 17 '18 at 22:05
  • Oh dear, that's quite a big mistake then! So it seems that the second value in password_verify() needs to be $user['hash'] instead of $user['password'] – Tolli Dec 21 '18 at 23:26