Skip to Content
Course content

160: Building a Session-Based Authentication System

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I want to start this lesson with a snippet of code that I've seen a lot of developers struggle with. It looks perfectly logical on the surface, but it fails every single time. Imagine you've just built a login page that successfully verifies a user's password and sets a session variable. Now, you've created a dashboard.php page that should only be accessible to logged-in users.

// dashboard.php
if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit();
}

echo "Welcome to your dashboard, " . $_SESSION['username'] . "!";

You test it, and no matter how many times you log in, you are immediately kicked back to the login page. You check your login.php and the session is definitely being set. You check your browser cookies and the session ID is there. You're staring at the screen wondering why PHP is "forgetting" who you are.

The Ghost Session Problem

The issue here is subtle because it's an omission rather than a syntax error. In PHP, the $_SESSION superglobal isn't magically available on every page just because you started a session on a previous page. PHP is stateless. Every time a new request hits the server, PHP starts from scratch.

When you call $_SESSION['user_id'] in the code above, PHP looks at the $_SESSION array. Since you haven't told PHP to resume the session for this specific request, that array is empty. The isset() check fails, and you get redirected. I've spent more hours than I'd like to admit debugging this exact thing in my early years.

Resuming the Session State

To fix this, you have to call session_start() at the very top of every single file that needs to access session data. This function tells PHP to look for the session ID cookie sent by the browser, find the corresponding data file on the server, and populate the $_SESSION array for you.

// dashboard.php
session_start(); // This must come before any output!

if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit();
}

echo "Welcome to your dashboard, " . $_SESSION['username'] . "!";

One pro tip: always put session_start() before any HTML tags or even a single whitespace character. If PHP sends a single byte of output to the browser, it sends the HTTP headers. Since sessions rely on cookies (which are sent in the headers), calling session_start() after output will trigger a "headers already sent" warning and the session won't initialize.

Structuring the Authentication Flow

When building a full system, I recommend separating your "auth check" into its own file. You don't want to copy-paste that if(!isset...) block into twenty different pages. Instead, create a file called auth_check.php:

// auth_check.php
session_start();
if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit();
}

Now, your protected pages become incredibly clean. You just require that file at the top, and if the user isn't logged in, the script dies and redirects them before any sensitive content is rendered.

Tearing Down the Session

Logging in is the easy part; logging out is where people often leave security holes. Simply calling unset($_SESSION['user_id']) removes the variable from the current script, but the session file still exists on the server, and the cookie still exists in the browser. To properly kill a session, you need to clear the array and destroy the server-side data.

// logout.php
session_start();

// 1. Clear all session variables
$_SESSION = [];

// 2. Destroy the session cookie in the browser
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// 3. Destroy the session on the server
session_destroy();

header("Location: login.php");
exit();


I know that looks like a lot of boilerplate for a logout script, but it's the only way to ensure the session is truly gone. This prevents "session replay" attacks where someone might try to use an old session ID to gain access.




📋 Practical Task

Build a Protected User Settings Page with Session Validation

Your task is to create a mini-authentication system consisting of three files. You don't need a real database for this; you can simulate a user check with a hardcoded array.

  • login.php: Create a form that accepts a username and password. If the username is "admin" and password is "secret123", start a session and store user_id = 1 and username = 'Admin' in the $_SESSION array, then redirect to the settings page.
  • settings.php: This page must be protected. Use a separate include file (e.g., auth_check.php) to ensure the user is logged in. If they are, display a "User Settings" heading and a link to the logout page.
  • logout.php: Implement a full session teardown that clears the $_SESSION array, deletes the session cookie, and destroys the session on the server before redirecting back to login.php.

Requirement: Ensure that if a user tries to access settings.php directly via the URL without logging in, they are immediately redirected to the login page.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.