-1

I have this simple login form that fails on password verification. I have done the exact same code on a different project and it worked like intended. The Mysql database is set up exactly the same way as the last project (password row for the hashed password is VARCHAR 255). I've also checked the UTF-8 both in the database and the Html and they look to be ok. I have a registration form that passes the hashed password into the table with BCRYPT. I have posted the log-in code below (the echo lines are for debugging and they return exactly what was expected).

if(isset($_POST['submit-login'])){
  function validateFormData($formData){
    $formData = trim(stripslashes(htmlspecialchars($formData)));
    return $formData;
  }
  
  $userEmail = validateFormData($_POST['login-email']);
  $password = validateFormData($_POST['login-password']);
  echo $password;
  echo $userEmail;
  include('includes/dbconn.php');
  $query = "SELECT firstname, lastname, email, pass FROM users WHERE email='$userEmail'";
  $result = mysqli_query( $conn, $query );

  if(mysqli_num_rows($result) > 0){
    while( $row = mysqli_fetch_assoc($result) ){
      $firstName = $row['firstname'];
      $lastName = $row['lastname'];
      $email = $row['email'];
      $hashedPass = $row['pass'];
      echo $hashedPass;
    }
    
    if( password_verify( $password, $hashedPass ) ){
      session_start();
      $_SESSION['firstname'] = $firstName;
      $_SESSION['lastname'] = $lastname;
      $_SESSION['email'] = $email;
      header("Location: dashboard.php");
    }else {
      $loginError = "<div class='text-center alert alert-danger'>Wrong username / password. Try again. </div>";
      
    }
  }else {
    $loginError = "<div class='text-center alert alert-danger alert-dismissible'>User not found! <button class='btn-close' data-dismiss='alert'></button></div>";
  }
  mysqli_close($conn);
}

There must be something I'm missing but I can't figure it out. It always returns the $loginError from the password_verify if statement.

Alex Toma
  • 35
  • 5
  • Does this answer your question? [password\_verify function not working](https://stackoverflow.com/questions/35665641/password-verify-function-not-working) – DarkBee Feb 04 '22 at 08:47
  • Not really, that is PDO I believe – Alex Toma Feb 04 '22 at 08:51
  • 1
    The function `validateFormData` is altering the posted data. You should not do this, especially not on a password field. Instead of using this function you should move to prepared statements. One of the problems this can yield is that the saved password is nowhere the same as the one after applying that function on it – DarkBee Feb 04 '22 at 08:51
  • using `WHERE email='$userEmail'` sort of negates the benefits of hashing the password as you have opened this to sql injection – Professor Abronsius Feb 04 '22 at 08:52
  • I'll try taking the function off the password field and see if that works – Alex Toma Feb 04 '22 at 08:52
  • 3
    No.. You should use prepared statements as you will be open to SQL injection otherwise – DarkBee Feb 04 '22 at 08:53
  • I'll try prepared statements as soon as I figure out how. Thanks! – Alex Toma Feb 04 '22 at 08:54
  • If you manipulate a user's input like you do here you might well invalidate the data in the process and no matter how good the rest of the logic it will still fail because you have fundamentally altered it – Professor Abronsius Feb 04 '22 at 09:06
  • **Warning:** You are wide open to [SQL Injections](https://php.net/manual/en/security.database.sql-injection.php) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Feb 04 '22 at 09:10
  • Why do you have a `while()` loop around your results retrieval? There's surely only going to be one matching result. If you have somehow got two in the database for the same email address, you'll never be sure which one you are checking against as you have no ORDER BY clause. – droopsnoot Feb 04 '22 at 09:20

2 Answers2

1

To use a prepared statement you might try like this.

Initially test that the required POST variables are set - there is little point testing if the submit button is within the POST data if the other fields are not ( an attacker might have used curl for instance ) and only proceed if that test is passed. Prepare the base SQL with a placeholder for the user supplied input - the email address in this case. Bind that placeholder to the posted variable and execute the command. As you specify explicitly the fields of interest in the sql you can use bind_result to associate the column values with php variables that will be populated when fetch is called.

With the variables you can then invoke the password_verify routine and take whatever action necessary upon success/failure.

<?php

    session_start();
    $msg = "<div class='text-center alert alert-danger'>Wrong username / password. Try again. </div>";

    if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
        $_POST['login-email'],
        $_POST['login-password']
    )){
        
        include 'includes/dbconn.php';
        
        $sql='select `firstname`, `lastname`, `email`, `pass` FROM `users` WHERE `email`=?';
        $stmt=$conn->prepare( $sql );
        
        $stmt->bind_param( 's', $_POST['login-email'] );
        $stmt->execute();
        $stmt->bind_result( $firstname, $lastname, $email, $pwdhash );
        $stmt->fetch();
        $stmt->free_result();
        $stmt->close();
        $conn->close();
        
        
        
        if( password_verify( $_POST['login-password'], $pwdhash ) ){
            $_SESSION['firstname'] = $firstname;
            $_SESSION['lastname'] = $lastname;
            $_SESSION['email'] = $email;
            
            exit( header("Location: dashboard.php") );
        }
        
        echo $msg;
    }
?>
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • I actually understood the process, the idea behind it, and made the code work. I guess all bumps in the road lead to knowledge. Thank you! – Alex Toma Feb 04 '22 at 13:25
-1

Check that your $hashedPass is a string and make sure that it is exist in your database ...

I think that this while is not working.

while( $row = mysqli_fetch_assoc($result) ){
      $firstName = $row['firstname'];
      $lastName = $row['lastname'];
      $email = $row['email'];
      $hashedPass = $row['pass'];
      echo $hashedPass;
    }