1

At first I am using md5 for hashing but then I learn that password_hash is more secured, but when I tried to use it in my website it wont work. I've tried putting the code password_verify everywhere.

When I'm trying to login it just giving me an error of password/ email combination is wrong even if it is correct. I also get the error for the password verify but when I put the correct credentials it's still giving me the error message

This is my login code

  <?php
  function login(){
  global $db, $email, $errors;

  // grab form values
  $email = e($_POST['email']);
  $password = e($_POST['password']);

  // make sure form is filled properly
  if (empty($email)) {
    array_push($errors, "Email is required");
}else {
    $email = hsc($_POST["email"]);
}

if (empty($password)) {
    array_push($errors, "Password is required");
}else{
    $password = hsc($_POST["password"]);
}

// attempt login if no errors on form
if (count($errors) == 0) {
    $query = "SELECT * FROM accounts WHERE email='$email' AND password='$password' LIMIT 1";
    $results = mysqli_query($db, $query);

if (password_verify($password, $_POST["password"])) {
  array_push($errors, "Wrong password");
}

    if (mysqli_num_rows($results) == 1) { // user found
        // check if user is admin or user
        $logged_in_user = mysqli_fetch_assoc($results);
 
        if ($logged_in_user['user_type'] == 'admin') {

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

            header('location: admin/admin.php');
            exit(0);
        }else{
            $_SESSION['user'] = $logged_in_user;
            $_SESSION['success']  = "You are now logged in";

            header('location: index.php');
            exit(0);
        }

    }else {
        array_push($errors, "Wrong username/password combination");
    }
}
}

This is my register code (There are all in the same file functions.inc.php)

      function register(){
        // call these variables with the global keyword to make them available in function
        global $db, $errors, $username, $email;

       // receive all input values from the form. Call the e() function
       // defined below to escape form values
     $username    =  e($_POST['username']);
     $email       =  e($_POST['email']);
     $password_1  =  e($_POST['password']);
     $password_2  =  e($_POST['re-password']);

  //check email if already exist on database
  $check = "SELECT * FROM accounts WHERE email='$email'";
  $res_e = mysqli_query($db, $check);

   // form validation: ensure that the form is correctly filled
   if (empty($username)) {
    array_push($errors, "Name is required");
    }elseif (!preg_match("/^[a-zA-Z]+( [a-zA-Z]+)*$/",$username)) {
    array_push($errors, "Only letters and one space only");
    }else{
    $username = hsc($_POST["username"]);
    }

   if (empty($email)) {
    array_push($errors, "Email is required");
    }elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    array_push($errors, "The email is invalid");
    }elseif (mysqli_num_rows($res_e) > 0) {
    array_push($errors, "The email already taken");
    }else{
    $email = hsc($_POST["email"]);
    }

   if (empty($password_1)) {
    array_push($errors, "Password is required");
    }elseif ($password_1 != $password_2) {
    array_push($errors, "The two passwords do not match");
    }else{
        $password_1 = hsc($_POST["password_1"]);
    }



   // register user if there are no errors in the form
  if (count($errors) == 0) {
    $hashpassword = password_hash($password_1, PASSWORD_DEFAULT);;//encrypt the password before 
    saving in the database

    if (isset($_POST['user_type'])) {
        $user_type = e($_POST['user_type']);
        $query = "INSERT INTO accounts (username, email, user_type, password) 
                  VALUES('$username', '$email', '$user_type', '$hashpassword')";
        mysqli_query($db, $query);

        $_SESSION['add']  = "Added successfully";
        header('location: users.php');
        exit(0);
    }else{
        $query = "INSERT INTO accounts (username, email, user_type, password) 
                  VALUES('$username', '$email', 'user', '$hashpassword')";
        mysqli_query($db, $query);

        // get id of the created user
        $logged_in_user_id = mysqli_insert_id($db);
        $_SESSION['user'] = getUserById($logged_in_user_id); // put logged in user in session
        $_SESSION['add']  = "You are now logged in and thank you!";

        header('location: index.php');
        exit(0);
    }
}

}

I don't know if this is also the reason that the login is not working but it is better that I put it in. This is the code for function hsc() and e()

// escape string
function e($val){
global $db;
return mysqli_real_escape_string($db, trim($val));
}

// htmlspecialchars the inputs data
function hsc($val) {
$val = htmlspecialchars($val);
return $val;
}

Here is the data base photo

  • 1
    You need to drop matching on ` AND password='$password' ` as the password is retrieved from the database to use in `password_verify` (so don't use `$_POST` but the value from the database. – Nigel Ren May 27 '21 at 18:57
  • Use PHP PDO! Your code is vulnerable to SQL injection attacks See: https://www.php.net/manual/en/security.database.sql-injection.php – Manu G May 27 '21 at 19:07
  • What do you mean by drop matching? – Aljon Gabriel Valdez May 27 '21 at 19:18
  • `What do you mean by drop matching`... It means exactly what it said - drop (i.e. remove) the SQL code which is shown in the comment – ADyson May 27 '21 at 21:45

1 Answers1

0

(By far the simplest method...) Try this example. It uses Argon2, which is by far the safest encryption method (AFAIK)

Note that it randomly generates a different string when run, so using password_verify is mandatory unlike using sha-256 to look up the password in the database

<?php
$pwd = password_hash("my password goes here", PASSWORD_ARGON2I);
// Use $_POST instead
echo $pwd;
?>

And to verify your password:

if(password_verify($_POST['password'], $row["password"])) {
 // Your code here... 
}

Also, use PDP PDO, it's much safer against SQL injection attacks

<?php
$db = new PDO('mysql:host='.$servername.';dbname='.$dbname.';charset=utf8mb4', $username, $password);
try {
  $query = "SELECT * from `login` WHERE `username`=:username OR `email` =:usernamea";
  $stmt = $db->prepare($query);
  $stmt->bindParam('username', $username, PDO::PARAM_STR);
  $stmt->bindParam('usernamea', $username, PDO::PARAM_STR);
  $stmt->execute();
  $count = $stmt->rowCount();
  $row   = $stmt->fetch(PDO::FETCH_ASSOC);
  if($count == 1 && !empty($row)) {
      $auth_email = $row['email'];
      $auth_pwd = $row['password'];
      if(password_verify($_POST['password'], $auth_pwd)) {
         $validuser = $row['username'];
         $_SESSION['valid'] = $validuser;
         $_SESSION['name'] = htmlspecialchars($row['name']);
      }
      else {
    echo 'Invalid';
     }
  } 
  else {
    echo 'Invalid';
  }
} 
catch (PDOException $e) { echo "Error : ".$e->getMessage(); }
?>
Manu G
  • 158
  • 5
  • 13
  • Hi, so I just need to change the password default to password argoni? Then should I use post for the password on the method of hashing? Is that should be positive not !? – Aljon Gabriel Valdez May 27 '21 at 19:03
  • Also where should I put that password_verify in my code? beucase I tried putting it any where it still giving me the same error and not logging in the user. – Aljon Gabriel Valdez May 27 '21 at 19:05
  • Check out my edit. Look at the last block of code – Manu G May 27 '21 at 19:05
  • Yes, thank you. I will try that soon. – Aljon Gabriel Valdez May 27 '21 at 19:05
  • You can still use prepared statements in mysqli, you don't need to move to PDO. – Nigel Ren May 27 '21 at 19:10
  • Really? I didn't know that! Thanks for letting me know – Manu G May 27 '21 at 19:12
  • Which is safer prepared statements or pdo and what are there difference? Let me trying searching this pdo – Aljon Gabriel Valdez May 27 '21 at 19:18
  • 1
    `by far the safest encryption method`... Terminology note: this is hashing, not encryption. They are very different. Encryption is not appropriate for storing passwords because it's reversible (unlike hashing) – ADyson May 27 '21 at 21:45
  • 1
    `Also, use PDP PDO, it's much safer against SQL injection attacks`...no, prepared statements and parameters are what protects you against SQL injection. You can write vulnerable queries using PDO just as easily as you can with mysqli. Equally, you can write safe queries using parameters just as easily using mysqli as you can with PDO. Don't attribute the protection to the wrong thing, it's misleading – ADyson May 27 '21 at 21:49
  • One more thing is this a $db = new PDO('mysql:host='.$servername.';dbname='.$dbname.';charset=utf8mb4', $username, $password); I mean db connection – Aljon Gabriel Valdez May 28 '21 at 03:32
  • Thank you, I just used prepared statements. I dont yet still know how the pdo works. – Aljon Gabriel Valdez May 28 '21 at 09:08