Skip to content
Advertisement

Session variable in PHP allows me to log in even though credentials are incorrect

I have a question about sessions. I noticed something unusual when I was testing my PHP code. Basically, I have two courses and the credentials are stored in their own database.

  • Example: Course 1: Username: abc Password: 123, database table: flitpc
  • Example: Course 2: Username: abc Password: 999, database table: itst

So the code below determines the login for the respective courses (both exactly same code for each course with the difference being the database table)

<?php   
// Initialize the session   
session_start();    
    
// Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){ 
  header("location: index");    
  exit; 
}   
    
// Include config file  
require_once "config.php";  
    
// Define variables and initialize with empty values    
$username = $password = ""; 
$username_err = $password_err = ""; 
    
// Processing form data when form is submitted  
if($_SERVER["REQUEST_METHOD"] == "POST"){   
    
    // Check if username is empty   
    if(empty(trim($_POST["username"]))){    
        $username_err = "Please enter username";    
    } else{ 
        $username = trim($_POST["username"]);   
    }   
        
    // Check if password is empty   
    if(empty(trim($_POST["password"]))){    
        $password_err = "Please enter your password";   
    } else{ 
        $password = trim($_POST["password"]);   
    }   
        
    // Validate credentials 
    if(empty($username_err) && empty($password_err)){   
        // Prepare a select statement   
        $sql = "SELECT id, username, password FROM flitpcusers WHERE username = ?"; 
            
        if($stmt = mysqli_prepare($link, $sql)){    
            // Bind variables to the prepared statement as parameters   
            mysqli_stmt_bind_param($stmt, "s", $param_username);    
                
            // Set parameters   
            $param_username = $username;    
                
            // Attempt to execute the prepared statement    
            if(mysqli_stmt_execute($stmt)){ 
                // Store result 
                mysqli_stmt_store_result($stmt);    
                    
                // Check if username exists, if yes then verify password    
                if(mysqli_stmt_num_rows($stmt) == 1){                       
                    // Bind result variables    
                    mysqli_stmt_bind_result($stmt, $id, $username, $hashed_password);   
                    if(mysqli_stmt_fetch($stmt)){   
                        if(password_verify($password, $hashed_password)){   
                            // Password is correct, so start a new session  
                            session_start();    
                                
                            // Store data in session variables  
                            $_SESSION["loggedin"] = true;   
                            $_SESSION["id"] = $id;  
                            $_SESSION["username"] = $username;                              
                                
                            // Redirect user to welcome page    
                            header("location: index.php");  
                        } else{ 
                            // Display an error message if password is not valid    
                            $password_err = "The password you entered was not valid";   
                        }   
                    }   
                } else{ 
                    // Display an error message if username doesn't exist   
                    $username_err = "No account found with that username";  
                }   
            } else{ 
                echo "Oops! Something went wrong. Please try again later."; 
            }   
            // Close statement  
            mysqli_stmt_close($stmt);   
        }   
    }   
        
    // Close connection 
    mysqli_close($link);    
}   
?>

So here is the thing, I have both tabs open on my browser, 1 for course 1, other for course 2.

Defect

  • Tab 1: I log into course 1 with its credentials, works fine, I don’t log out.

  • Tab 2: I log into course 2 with course 2 username (same username as course 1), but I also use course 1 password, it logs me in,

  • Now if I log out of both courses and try the second bullet point above again, I can’t log in.

So it’s unusual and I want to know how to fix this and understand a little bit more about sessions as I think it’s related to that.

Update

I have also found out it doesn’t matter if usernames are different. It may be recognising the same password used for both login.

Advertisement

Answer

Authentication is never actually performed in tab 2. Because you already have a session you’re redirected to the index when you hit this code block:

// Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){ 
  header("location: index");    
  exit; 
} 

You need to save course somewhere in $_SESSION and check if an appropriate session not only exists but matches the course, otherwise authentication using table 1 credentials is indistinguishable from authentication using table 2 credentials.

EDIT:

After authentication save from where the authentication occurred:

// Store data in session variables  
$_SESSION["loggedin"] = true;   
$_SESSION["id"] = $id;  
$_SESSION["username"] = $username; 
$_SESSION["authenticated_from"] = "flitpcusers";

Then when you’re checking if a $_SESSION exists also check if it’s for the appropriate course, so:

// Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true && $_SESSION["authenticated_from"]==="flitpcusers"){ 
  header("location: index");    
  exit; 
}

This will prevent a table 1 authenticated session as being recognized as a table 2 session.

While the above will fix the strange behaviors you’re observing I’d really look at redesigning your database scheme here. It’s strange that I need to authenticate differently for different courses. Ideally I authenticate once and that authentication is used for any/all services under that identity. Look at Google: I don’t have to login to Youtube then login to Gmail then login to Search, I log in once and then Google servers determine which services I have access to.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement