Building a Simple Authentication System: Secure PHP Basics
Master authentication in PHP by implementing secure password hashing and session management to protect your application's routes effectively.

Previously in this course, we discussed Database Transactions to ensure our data remains consistent. In this lesson, we build on that foundation by implementing a secure authentication system, focusing on password hashing and session management to control access to your application.
The Security Mindset: Hashing vs. Encryption
The cardinal rule of authentication is simple: never store passwords in plain text. If your database is compromised, a plain-text password list is a disaster for your users.
Instead, we use password hashing. Hashing is a one-way transformation: you convert a password into a unique string of characters. You cannot "decrypt" a hash to reveal the original password. When a user logs in, you re-hash their input and compare it to the stored hash.
In modern PHP, we use password_hash() and password_verify(). These functions automatically handle "salting"—adding random data to the password before hashing to prevent rainbow table attacks.
Implementing Authentication Logic
To integrate this into our MVC project, we need two core methods in our User model.
PHPclass User { #6A9955">// Hash a password before saving to the DB public function register(string $username, string $password): bool { $hashedPassword = password_hash($password, PASSWORD_DEFAULT); $stmt = $this->db->prepare("INSERT INTO users(username, password) VALUES(?, ?)"); return $stmt->execute([$username, $hashedPassword]); } #6A9955">// Verify a login attempt public function authenticate(string $username, string $password): ?array { $stmt = $this->db->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password'])) { return $user; } return null; } }
Protecting Routes with Session Management
Once a user is verified, we must persist their state. As discussed in Managing State with Superglobals, we use sessions to store the user's ID after a successful login.
To protect a route, you simply check if the user identity exists in the session. Here is how you might implement this in a Controller:
PHPclass DashboardController { public function index() { session_start(); if (!isset($_SESSION['user_id'])) { header('Location: /login'); exit; } #6A9955">// Render the dashboard view require 'views/dashboard.php'; } }
Comparison: Authentication vs. Authorization
While authentication confirms who the user is, authorization confirms what they can do.
| Concept | Purpose | Implementation |
|---|---|---|
| Authentication | Verifies identity | Login forms, password hashing |
| Authorization | Checks permissions | Role checks, access control lists |
Hands-on Exercise: The Login Gate
- Update your
Usermodel to include theauthenticatemethod shown above. - Create a
LoginControllerthat handles the POST request from a login form. - If
authenticatereturns a user array, store theuser_idin$_SESSION. - Create a protected controller method that checks
$_SESSION['user_id']and redirects guests to the login page.
Common Pitfalls
- Weak Hashing Algorithms: Never use
md5()orsha1()for passwords. They are cryptographically broken and fast to crack. Always usePASSWORD_DEFAULT. - Forgetting
exit: When redirecting withheader('Location: ...'), always follow it withexit. Otherwise, the remainder of your script will continue to execute, potentially revealing protected information. - Case Sensitivity: Ensure your password comparison is strict.
password_verifyis designed for this, but if you manually compare strings, usehash_equals()to prevent timing attacks.
FAQ
Why does password_hash return a different string every time?
It includes a unique salt in the output string. This ensures that even if two users have the same password, their stored hashes will look different.
How do I handle "Remember Me" functionality? That requires persistent cookies, which are more complex than standard session management. Stick to standard sessions until you are comfortable with secure token storage.
Can I store user roles in the session?
Yes, once you verify the password, you can store the user's role (e.g., 'admin') in $_SESSION['role'] to simplify permission checks later.
Recap
We've implemented a secure authentication flow: hashing passwords with password_hash(), verifying them with password_verify(), and locking down routes by checking $_SESSION state. These tools are the foundation of user security in your MVC application.
Up next: We will explore how to manage time and dates effectively using the DateTime class.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

VPS Server Setup, Deployment & Hardening
Get your app live on a fast, secure server — properly configured, hardened, and deployment-ready. No more wrestling with the command line.


