Module 3: User Authentication & Management

Let's build the gateway to our admin area. This module covers creating a secure login and registration system.

Securing Our Application

User authentication is a fundamental requirement for our management system. We need a way to ensure that only authorized personnel (admins and staff) can access the dashboard to manage products, orders, and other sensitive data. In this module, we will build the complete authentication flow from the ground up.

Key concepts we'll cover:

  • Connecting to the database securely.
  • Hashing passwords to protect user credentials.
  • Using PHP sessions to keep users logged in.
  • Restricting access to certain pages based on login status.

Step 1: The Database Connection File

To avoid repeating the database connection code on every page, we'll create a central connection file. Create a new file named `db.php` inside your `includes/` folder and add the following code.

includes/db.php
<?php
// Database configuration
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', ''); // Your DB password, likely empty for default XAMPP
define('DB_NAME', 'bakery_db');

// Attempt to connect to MySQL database
$conn = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);

// Check connection
if($conn === false){
    die("ERROR: Could not connect. " . $conn->connect_error);
}
?>
                            

Step 2: Building the Registration Page

First, we need a way to add new users to our `users` table. Let's create a `register.php` file in the main project directory.

The crucial part of the PHP code is hashing the password. We will use the built-in `password_hash()` function, which creates a strong, salted hash, making it extremely difficult for attackers to reverse.

register.php
<?php
require_once 'includes/db.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $username = $_POST['username'];
    $password = $_POST['password'];
    $role = $_POST['role']; // 'admin' or 'staff'

    // Hash the password for security
    $hashed_password = password_hash($password, PASSWORD_DEFAULT);

    $sql = "INSERT INTO users (username, password, role) VALUES (?, ?, ?)";
    
    if ($stmt = $conn->prepare($sql)) {
        $stmt->bind_param("sss", $username, $hashed_password, $role);
        
        if ($stmt->execute()) {
            echo "Registration successful!";
        } else {
            echo "Error: " . $stmt->error;
        }
        $stmt->close();
    }
    $conn->close();
}
?>
<!-- HTML form for registration -->
<form action="register.php" method="post">
    <input type="text" name="username" placeholder="Username" required>
    <input type="password" name="password" placeholder="Password" required>
    <select name="role">
        <option value="staff">Staff</option>
        <option value="admin">Admin</option>
    </select>
    <button type="submit">Register</button>
</form>
                            

Step 3: Building the Login Page

Now, let's create the login functionality. When a user tries to log in, we'll fetch their record from the database and use `password_verify()` to check if the submitted password matches the stored hash.

We'll also introduce PHP sessions. A session is a way to store information (in variables) to be used across multiple pages. We start a session using `session_start()` and store the user's ID and role once they log in successfully.

login.php
<?php
session_start();
require_once 'includes/db.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $username = $_POST['username'];
    $password = $_POST['password'];

    $sql = "SELECT id, username, password, role FROM users WHERE username = ?";
    
    if ($stmt = $conn->prepare($sql)) {
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();
        
        if ($stmt->num_rows == 1) {
            $stmt->bind_result($id, $username, $hashed_password, $role);
            if ($stmt->fetch()) {
                if (password_verify($password, $hashed_password)) {
                    // Password is correct, start a new session
                    $_SESSION["loggedin"] = true;
                    $_SESSION["id"] = $id;
                    $_SESSION["username"] = $username;
                    $_SESSION["role"] = $role;
                    
                    // Redirect to a welcome page
                    header("location: admin/dashboard.php");
                } else {
                    echo "Invalid password.";
                }
            }
        } else {
            echo "No account found with that username.";
        }
        $stmt->close();
    }
    $conn->close();
}
?>
<!-- HTML form for login -->
<form action="login.php" method="post">
    <input type="text" name="username" placeholder="Username" required>
    <input type="password" name="password" placeholder="Password" required>
    <button type="submit">Login</button>
</form>
                            

Step 4: The Dashboard and Logging Out

Our system is useless if anyone can access the admin pages. Let's create a simple dashboard and protect it. At the top of any page you want to protect, add a check to see if the `$_SESSION["loggedin"]` variable is true. If not, redirect them to the login page.

admin/dashboard.php
<?php
session_start();

// If user is not logged in, redirect to login page
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
    header("location: ../login.php");
    exit;
}
?>
<h1>Welcome, <?php echo htmlspecialchars($_SESSION["username"]); ?>!</h1>
<p>Your role is: <b><?php echo $_SESSION["role"]; ?></b></p>
<a href="../logout.php">Logout</a>
                            

Finally, the logout script is simple. It unsets all session variables and destroys the session, effectively logging the user out.

logout.php
<?php
session_start();

// Unset all of the session variables
$_SESSION = array();

// Destroy the session.
session_destroy();

// Redirect to login page
header("location: login.php");
exit;
?>