0

I'm trying to create a login system that checks for user role and redirects to the corresponding dashboard, while also forbidding users from manually entering others' dashboard URLs.

The login is working great, but the check for user role, not so much.

The site has one dashboard for each role, and on top of each is this:

session_start(); 
if(!$_SESSION['sess_role'] == 'role1') {
    header('location:../../index.php');
}

It seems to work when you haven't logged in, sending you back to the index page correctly because the 'sess_role' attribute does not match, but once I login with ANY user, I'm able to enter EVERY single dashboard by manually entering the URL, despite not having the correct "role" for it.

Here's the login code:

$msg = ""; 
if(isset($_POST['submitBtnLogin'])) {
    $username = trim($_POST['username']);
    $password = trim($_POST['password']);
    if($username != "" && $password != "") {
        try {
            $query = "select * from `users` where `username`=:username and `password`=:password";
            $stmt = $db->prepare($query);
            $stmt->bindParam('username', $username, PDO::PARAM_STR);
            $stmt->bindValue('password', $password, PDO::PARAM_STR);
            $stmt->execute();
            $count = $stmt->rowCount();
            $row   = $stmt->fetch(PDO::FETCH_ASSOC);
            if($count == 1 && !empty($row)) {

                $_SESSION['sess_user_id']   = $row['id'];
                $_SESSION['sess_username'] = $row['username'];
                $_SESSION['sess_role'] = $row['role'];
            }

                if($row['role'] == "role1") {
                header('location:modules/role1/index.php');
                } else if($row['role'] == "role2") {
                header('location:modules/role2/index.php');
                } else if($row['role'] == "role3") {
                header('location:modules/role3/index.php');
                } else if($row['role'] == "role4") {
                header('location:modules/role4/index.php');

            } else {
                $msg = "Invalid login information.";
            }
        } catch (PDOException $e) {
            echo "Error : ".$e->getMessage();
        }
    } else {
        $msg = "Both fields are required.";
    }
}

I tried doing:

echo($_SESSION['sess_role']);

To see what the output is, and it seems to work as intended, showing "role1" when I'm on a "role1" account, and the same for the other roles.

While accessing "role2" dashboard, for example, the output is still "role1" but I'm still able to enter.

I'd greatly appreciate some help on identifying the issue.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • You should add `exit;` after each header. Your code is probably wanting to continue to execute. Another thing; why are you storing plain text passwords? – Funk Forty Niner Jan 14 '19 at 00:44
  • well, seems this is it! after adding exit; where it was needed everything works correctly, thank you for helping! –  Jan 14 '19 at 02:38

2 Answers2

1

The ! operator binds to $_SESSION['sess_role'], not to the whole expression. You have to either put your expression in brackets if(!($_SESSION['sess_role'] == 'role2')) or better use the not equals operator for better readability if($_SESSION['sess_role'] != 'role2') {

sui
  • 751
  • 6
  • 10
  • tried both of your suggestions, but it seems the issue still persists with either –  Jan 14 '19 at 00:24
0

As it turns out and as per a comment I left, was cause for failure:

You should add exit; after each header. Your code is probably wanting to continue to execute.

Using a header with an exit is recommended, per the following Q&A here on Stack Overflow:

On an added note; don't store plain text passwords. Store a hashed version of it by using password_hash():

And then verifying them with password_verify():

Please read through those in its entirety, it's important.

Using just a prepared statement isn't safe enough, not when it comes to passwords.

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141