Skip to main content
PHP Backend Development Tutorial
CHAPTER 10 Beginner

User Authentication and Login Systems

Updated: May 14, 2026
25 min read

# CHAPTER 10

User Authentication and Login Systems

1. Introduction

The most critical responsibility of a backend developer is protecting user data. When a user creates an account, they trust you with their password. If you store that password incorrectly and a hacker breaches your database, the consequences are catastrophic. In this chapter, we will build a complete, production-ready Registration and Login system using modern cryptographic hashing and session-based access control.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the extreme danger of storing plain-text passwords.
  • Use password_hash() to securely encrypt passwords.
  • Use password_verify() during the login process.
  • Implement strict access control to protect private web pages.

3. Beginner-Friendly Explanation

Imagine a medieval castle (your database). If the King writes down the secret password to the vault on a piece of paper and puts it in the library, a spy can sneak in, read the paper, and steal the gold. This is storing Plain-Text Passwords. Instead, the King uses a magical cipher. He takes the password "apple," runs it through the cipher, and writes down x$9ZqLp2. Even if the spy steals the paper, they have no idea what it means. When a knight wants to enter the vault, they whisper "apple," the King runs it through the cipher, checks if it equals x$9ZqLp2, and lets them in. This is Password Hashing.

4. The Golden Rule: Never Store Plain-Text Passwords

If your MySQL database looks like this:
idemailpassword
1user@test.compassword123
You have failed as a backend developer. If your database is leaked, hackers immediately have everyone's exact password, which they will use to break into the users' banking and email accounts.

5. Registration (Hashing the Password)

When a user signs up, PHP uses a one-way mathematical algorithm (Bcrypt) to scramble the password into an unreadable "Hash." A one-way hash cannot be decrypted back into the original password, not even by the developer!
php
1234567891011121314151617
<?php
require &#039;db.php';

// Data from Registration Form
$email = $_POST[&#039;email'];
$raw_password = $_POST[&#039;password'];

// Hash the password securely
$hashed_password = password_hash($raw_password, PASSWORD_DEFAULT);

// Insert into Database using Prepared Statements
$sql = "INSERT INTO users (email, password) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email, $hashed_password]);

echo "Registration successful!";
?>

*Now, the database stores something like:* $2y$10$w8T.G3b1Gq4...

6. Login (Verifying the Password)

When the user tries to log in, you fetch the stored Hash from the database, and use PHP's built-in password_verify() function to see if the password they typed matches the Hash.
php
12345678910111213141516171819202122232425262728
<?php
session_start();
require &#039;db.php';

$login_email = $_POST[&#039;email'];
$login_password = $_POST[&#039;password'];

// 1. Find the user by email
$sql = "SELECT id, password FROM users WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$login_email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

// 2. Verify password AND check if user actually exists
if ($user && password_verify($login_password, $user[&#039;password'])) {
    
    // Passwords match! Log them in via Sessions
    $_SESSION[&#039;user_id'] = $user['id'];
    $_SESSION[&#039;logged_in'] = true;
    
    echo "Login successful! Redirecting to dashboard...";
    // header("Location: dashboard.php");
    
} else {
    // Vague error message prevents hackers from knowing if the email exists
    echo "Invalid email or password."; 
}
?>

7. Access Control (Protecting Pages)

Now that the user is logged in, you must protect your private pages (like dashboard.php). If a user who is *not* logged in tries to type www.yoursite.com/dashboard.php into their browser, the PHP script must kick them out.

At the very top of dashboard.php:

php
12345678910111213
<?php
session_start();

// If the session variable is NOT set, they are an intruder
if (!isset($_SESSION[&#039;logged_in']) || $_SESSION['logged_in'] !== true) {
    // Redirect them to the public login page
    header("Location: login.php");
    exit; // Stop the rest of the script from executing!
}

// If they pass the check, show the private page
echo "<h1>Welcome to the secure dashboard!</h1>";
?>

8. The Logout Script

To log the user out securely, destroy the session data and redirect them to the homepage.
php
1234567
<?php
session_start();
$_SESSION = array(); // Empty the array
session_destroy();   // Destroy the session
header("Location: index.php");
exit;
?>

9. Best Practices

  • Vague Error Messages: During login, never say "Password incorrect" or "Email not found." This tells hackers exactly which emails exist in your database, allowing them to target specific accounts. Always use: "Invalid credentials."

10. Common Mistakes

  • Forgetting exit; After a Redirect: When you use header("Location: login.php"); to kick out an intruder, the server sends the redirect header, *but it keeps executing the rest of the PHP file in the background!* A hacker can use software to ignore the redirect and scrape the private HTML data. You must ALWAYS put exit; immediately after a redirect.

11. Exercises

  1. 1. Explain why developers use password_hash() rather than two-way encryption algorithms that allow passwords to be decrypted back to plain text.

12. Coding Challenges

  • Challenge: Modify the Access Control script to check a user's role. If $_SESSION['role'] is not equal to 'Admin', redirect them to a page called access_denied.php.

13. MCQs with Answers

Question 1

What is the fundamental danger of storing plain-text passwords in a database?

Question 2

When protecting a private dashboard page from unauthorized visitors, what is the critical step you must take immediately after calling header("Location: login.php");?

14. Interview Questions

  • Q: Explain the modern PHP registration and login workflow. Specifically, how do password_hash() and password_verify() interact?
  • Q: What is the purpose of an "Access Control" block at the top of a private PHP file, and how does it utilize $_SESSION?

15. FAQs

Q: I found a tutorial online that uses md5() to hash passwords. Should I use that? A: NO. md5() and sha1() are completely broken, obsolete hashing algorithms. Hackers can reverse them in milliseconds using massive lookup tables. Modern PHP explicitly uses password_hash(), which utilizes the highly secure Bcrypt algorithm and automatically applies "salt" to prevent table attacks.

16. Summary

In Chapter 10, we mastered user security. By utilizing one-way hashing algorithms, we guarantee that even if our database is stolen, our users' passwords remain unreadable. By establishing a robust authentication workflow—verifying hashes, setting session tokens, and enforcing strict access control redirects on private pages—we built the impenetrable gates required for any modern web application.

17. Next Chapter Recommendation

Text data is easy, but what if a user wants to upload a profile picture? Proceed to Chapter 11: PHP File Uploads and File Handling to learn how to move physical files.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·