0

Every single time I try to log in, I tried several times with accounts in the database with passwords I am sure of, these are hashed then inserted into the database. However, whenever I use password_verify, I keep getting the error handler put in that says that the user has put wrong login credentials. Tried creating another user that contains ASCII character to check for encoding errors, but still didn't work.

<?php

require_once 'dbh.inc.php';

if (isset($_POST['login-submit'])) {
    $username = $_POST['username'];
    $pwd = $_POST['pwd'];

    if (empty($username) || empty($pwd)) {
        header('location: ../login.php?error=emptyfields');
        exit();
    } else {

        $sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
            header('location: ../login.php?error=stmtfailed');
            exit();
        } 

        mysqli_stmt_bind_param($stmt, "ss", $username, $username);
        mysqli_stmt_execute($stmt);
                

        $resultData = mysqli_stmt_get_result($stmt);
        mysqli_stmt_close($stmt);

        if (mysqli_fetch_assoc($resultData) == 0) { 
            header('location: ../login.php?error=usernonexistant');
            exit();
        }

        $row = mysqli_fetch_assoc($resultData);
        $pwdHashed = $row['pwd'];
        $checkPwd = password_verify($pwd, $pwdHashed);      

        if ($checkPwd === false) {
            header('location: ../login.php?error=wronglogincredentials');
            exit();
        } else if ($checkPwd === true) {    /*review this bruh*/ 
            session_start();
            $_SESSION['uid'] = mysqli_fetch_assoc($resultData) ['uid'];
            $_SESSION['username'] = mysqli_fetch_assoc($resultData) ['username'];
            header('location: ../index.php');
            exit();
        } 
    }
} else {
    header('location: ../login.php');
    exit();
}   
Dharman
  • 30,962
  • 25
  • 85
  • 135
samervjr
  • 29
  • 5
  • 2
    Aren't you invoking `mysqli_fetch_assoc()` four times? – Álvaro González Mar 06 '21 at 16:43
  • Please add this command after this line: `mysqli_stmt_close($stmt);`: `print_r($resultData); die();` and attach the output to your question – adampweb Mar 06 '21 at 16:50
  • 2
    `$resultData` is not a query, `mysqli_fetch_assoc` won't work that way ... and you have 2 `mysqli_fetch_assoc` and a total mixup of `stmt` and regular calls – Reflective Mar 06 '21 at 16:53
  • @Reflective No, 4X `mysqli_fetch_assoc` ... – adampweb Mar 06 '21 at 17:26
  • @Adam P. this is what I get : mysqli_result Object ( [current_field] => 0 [field_count] => 4 [lengths] => [num_rows] => 1 [type] => 0 ) – samervjr Mar 06 '21 at 17:26
  • @Reflective so what is it? And how do you select all from database where smthg when using prepared statements and put them in an arrray? – samervjr Mar 06 '21 at 17:31
  • please read https://www.php.net/manual/en/mysqli-result.fetch-assoc.php and see what `mysqli_query` does – Reflective Mar 06 '21 at 17:38
  • If you are only starting to learn PHP then you should learn PDO instead of mysqli. PDO is much easier and more suitable for beginners. Start here https://phpdelusions.net/pdo & https://websitebeaver.com/php-pdo-prepared-statements-to-prevent-sql-injection – Dharman Mar 06 '21 at 17:47
  • @Reflective I have absolutely no idea what you are saying. I am sorry but your comments don't make much sense. Can you explain this better? – Dharman Mar 06 '21 at 17:48
  • $sql = 'select * from tablename'; $query = mysqli_query($mysqli, $sql); $row = mysqli_fetch_assoc($query); – Reflective Mar 06 '21 at 17:54
  • 1
    @Reflective But that doesn't use prepared statements does it..? – samervjr Mar 06 '21 at 17:55
  • @Reflective OP uses prepared statements. `mysqli_query()` doesn't apply here – Dharman Mar 06 '21 at 17:57
  • @Dharman yeah exactly. What can i use here instead to get data from a column? – samervjr Mar 06 '21 at 18:02
  • @samervjr You are almost there, but you are not using `mysqli_fetch_assoc()` correctly. See my answer – Dharman Mar 06 '21 at 18:02

1 Answers1

1

Your problem is that you are calling mysqli_fetch_assoc() four times, but you only have one row. This function is not idempotent. Each time you call it, the internal pointer moves on to the next row. You have complicated the code way too much. If mysqli is too difficult for you, please try PDO.

The same code can be rewritten to make it simpler. After some small refactoring the code will look like this:

<?php

require_once 'dbh.inc.php';
session_start();

if (!isset($_POST['login-submit'])) {
    header('location: ../login.php');
    exit();
}

if (empty($_POST['username']) || empty($_POST['pwd'])) {
    header('location: ../login.php?error=emptyfields');
    exit();
}
$username = $_POST['username'];
$pwd = $_POST['pwd'];

$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? OR email = ?;");
$stmt->bind_param('ss', $username, $username);
$stmt->execute();
$resultData = $stmt->get_result();
$row = $resultData->fetch_assoc();

if (!$row) {
    header('location: ../login.php?error=usernonexistant');
    exit();
}

$checkPwd = password_verify($pwd, $row['pwd']);

if (!password_verify($pwd, $row['pwd'])) {
    header('location: ../login.php?error=wronglogincredentials');
    exit();
}

$_SESSION['uid'] = $row['uid'];
$_SESSION['username'] = $row['username'];
header('location: ../index.php');
exit();

In the above code, I removed the remaining three calls to mysqli_fetch_assoc() and used OO-style which is much easier to read. Be sure to enable mysqli error reporting. Read How to get the error message in MySQLi?

Dharman
  • 30,962
  • 25
  • 85
  • 135