-1

Hello I have been encountering this bug for a long time. So basically here is by code:

function loginUser($conn, $username, $password) {
    $checkExists = checkExists($conn, $username, $username);

    if ($checkExists === false) {
        header("Location: ../login.php?error=wronglogininfo");
        exit();
    }

    $passwordHashed = $checkExists['password'];
    $checkPassword = password_verify($password, $passwordHashed);

    if ($checkPassword === false) {
        header("Location: ../login.php?error=wronglogin");
        exit();
    } elseif ($checkPassword === true) {
        $query = "SELECT * FROM users WHERE username='$username' AND password='$checkPassword'";
        $query_run = mysqli_query($conn, $query);
        $usertypes = mysqli_fetch_array($query_run);

        if ($usertypes['usertype'] == "admin") {
            header('Location: ../login.php?admin');
        } elseif ($usertypes['usertype'] == "user") {
            header('Location: ../login.php?user');
        }
    }
}

function checkExists($conn, $username, $email) {
    $sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
    $stmt = mysqli_stmt_init($conn);

    if (!mysqli_stmt_prepare($stmt, $sql)) {
        header("Location: ../register.php?error=stmtfailed");
        exit();
    } 

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

    $resultData = mysqli_stmt_get_result($stmt);

    if ($row = mysqli_fetch_assoc($resultData)) {
        return $row;
    } else {
        $result = false;
        return $result;
    }
    
    mysqli_stmt_close($stmt);
}

And so the errors work fine. The real problem is that whenever I login with correct credentials it sends me to a 404 page with a directory I never put. I want it to send be to the admin panel or user page. Can anyone help?

Lunar
  • 5
  • 4
  • 1
    This select looks like a road to ruin: `SELECT * FROM users WHERE username='$username' AND password='$checkPassword'` If `$checkPassword` is the result of a `password_verify()`. (Also be careful about possible SQL injection.) – Progrock Jan 13 '21 at 01:33
  • I understand I am just a newbie at php so I am going to add SQL injection security later just trying to actually get the code finsished – Lunar Jan 13 '21 at 01:36
  • Then how would I change my select? – Lunar Jan 13 '21 at 01:37
  • So where does it send you? Is there something in the login page that we can't see that is doing another redirect? – waterloomatt Jan 13 '21 at 01:38
  • No the actual code is fine nothing is wrong I know something is wrong in the functions since this error happened before and the error was in the functions, I fixed that error. If you want to see here it is: – Lunar Jan 13 '21 at 01:39
  • If you already have the user row, via checkExists() (could this be named better?), why do another call to the database to get the usertype? – Progrock Jan 13 '21 at 01:45
  • (Sorry I can't think of anything else to name it) I tried removing variable $query, $query_run, $usertypes and used variable $row so it would look like if ($row['usertypes''] == "admin") { // code } elseif ($row['usertypes''] == "user") { // code } but this still doesn't work Do you need an image of the 404 directory error – Lunar Jan 13 '21 at 01:47
  • Why don't you use your browsers' developer toolbar (F12) and watch what happens in the Network tab? See where it is sending you. That'll be the fastest way to solve this. – waterloomatt Jan 13 '21 at 01:49
  • It isn't wrong with the directory it's something wrong with the code a bug like this occurred again but I was able to fix it and the bug was in the those 2 functions – Lunar Jan 13 '21 at 01:50
  • There are too many variables for us to guess. Some things I see: `Location: ../xxx` shouldn't be a relative path, what happens if `usertype` is neither admin nor user?, you should issue an `exit;` after your header calls, what is `include('../security/security.php');` doing? Could you in fact be successfully redirected to login.php but `security.php` is redirecting you somewhere else?, ... – waterloomatt Jan 13 '21 at 01:58
  • Did you read the very first comment in this thread? That is likely the source of your issues? That won't return anything, but your very next _if_ statement is expecting a row to be returned. – waterloomatt Jan 13 '21 at 02:09
  • **Never store passwords in clear text or using MD5/SHA1!** Only store password hashes created using PHP's [`password_hash()`](https://php.net/manual/en/function.password-hash.php), which you can then verify using [`password_verify()`](https://php.net/manual/en/function.password-verify.php). Take a look at this post: [How to use password_hash](https://stackoverflow.com/q/30279321/1839439) and learn more about [bcrypt & password hashing in PHP](https://stackoverflow.com/a/6337021/1839439) – Dharman Jan 13 '21 at 12:39
  • What have you tried to debug the problem? It should not be too hard to run through these lines using var_dump or XDebug to check **where** this goes wrong – Nico Haase Jan 13 '21 at 13:56
  • It is already solved. – Lunar Jan 14 '21 at 01:56
  • Thank you everyone for helping me solve this bug that I had (it really frustrated me). – Lunar Jan 14 '21 at 01:57

1 Answers1

0

This select looks like a road to ruin: SELECT * FROM users WHERE username='$username' AND password='$checkPassword' If $checkPassword is the result of a password_verify(). (Also be careful about possible SQL injection.)

I suspect this is your main issue. This would essentially translate your query to:

SELECT * FROM users WHERE username = 'tony' AND password = '1';

This will likely return an empty result set, but your very next if statement is expecting a user array populated with data.

if ($usertypes['usertype'] == "admin") {
    header('Location: ../login.php?admin');
} elseif ($usertypes['usertype'] == "user") {
    header('Location: ../login.php?user');
}

What happens now? You won't be redirected anywhere and the current script will continue processing. So what can you do?

If you already have the user row, via checkExists() (could this be named better?), why do another call to the database to get the usertype?

You already have access to your user array because you called checkExists above and verified it is not false. Just use the array directly.

I just cleaned up your code a bit and added in some comments. I did not alter your queries in any way and didn't verify they are correct.

function loginUser($conn, $username, $password) {

    // Renamed this variable
    // Validate it and use this variable for the remainder of the function.
    $user = checkExists($conn, $username, $username);

    if ($user === false) {
        header("Location: ../login.php?error=wronglogininfo");
        exit();
    }

    $passwordHashed = $user['password'];

    // Renamed this variable.
    $validPassword = password_verify($password, $passwordHashed);

    if ($validPassword === false) {
        header("Location: ../login.php?error=wronglogin");
        exit();
    }
    
    // You now know you have a user and a valid password. 
    // No need to select them again

    if ($user['usertype'] == "admin") {
        header('Location: ../login.php?admin');
        exit;
    } 

    if ($user['usertype'] == "user") {
        header('Location: ../login.php?user');
        exit;
    }

    // What happens if `usertype` not matched? You still need to handle this case?
}

function checkExists($conn, $username, $email) {
    $sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
    $stmt = mysqli_stmt_init($conn);

    if (!mysqli_stmt_prepare($stmt, $sql)) {
        header("Location: ../register.php?error=stmtfailed");
        exit();
    } 

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

    $resultData = mysqli_stmt_get_result($stmt);

    // Cleaned up this if statement
    if ($row = mysqli_fetch_assoc($resultData)) {
        return $row;
    }
   
    return false;   
}
waterloomatt
  • 3,444
  • 1
  • 18
  • 24
  • Good catch. Removed it which has the same net effect as the original code which returned before calling it. – waterloomatt Jan 13 '21 at 18:56
  • Oh my god, THANK YOU GUYS SO MUCH FOR HELPING ME! Also thanks for pointing that out if usertype is somehow not admin and user (most likely won't happen unless some bug occurs since I can only set it too those two types). – Lunar Jan 13 '21 at 23:55
  • @Lunar - so which piece(s) were causing the bug for you? – waterloomatt Jan 14 '21 at 00:54
  • 1
    The part where I had to add exits and probably not needing to use another else if – Lunar Jan 14 '21 at 01:51