Module 10: Authentication
Module Overview
This module teaches you how to add secure authentication to web applications. You will learn about PHP sessions, login/logout forms, password hashing, and protecting pages so only logged-in users can access them. By the end of this module, you will have a working authentication system that you can add to any project.
Estimated Duration: 6 hours
Prerequisites:
- Completion of Modules 1-9
- Basic understanding of PHP and MySQL
- A local development environment (XAMPP, WAMP, or similar)
- A text editor (VS Code recommended)
Tools Used:
- PHP 7.4+
- MySQL
- HTML/CSS
- Free AI tools (ChatGPT, Gemini, etc.)
Lesson 1: Understanding Sessions and Authentication Basics
Duration: 1 hour 15 minutes
Learning Objectives
- Explain what web authentication is and why it matters
- Understand how PHP sessions work
- Start and destroy sessions securely
- Create a basic session-based login system skeleton
- Verify AI-generated authentication code for common vulnerabilities
Instructor Notes
Students often confuse authentication (proving who you are) with authorization (what you can do). Emphasize that this lesson focuses on authentication. Remind them that session hijacking is a real risk, so secure session handling is critical. Stress that AI tools often forget to call session_start() on every protected page.
Presentation Outline
- Introduction (5 min)
What is authentication?
Why sessions? (HTTP is stateless)
- PHP Sessions Explained (15 min)
session_start()
$_SESSION superglobal
Session cookies
- Session Lifecycle (15 min)
Creating a session
Storing data
Destroying a session
- Common Mistakes (15 min)
Forgetting session_start()
Exposing session IDs in URLs
Not regenerating session IDs
- Q&A and Preview (5 min)
Demonstration
Follow these steps to build a basic session demo:
- Create
session-demo.php in your project folder.
- Add the opening PHP tag and start the session at the very top of the file.
- Check if a
username key exists in the $_SESSION array.
- If it exists, display a welcome message with the username.
- If it does not exist, display a login form that submits back to the same page.
- When the form is submitted, store the username in
$_SESSION and refresh the page.
- Add a logout link that calls
session_destroy() and redirects to the same page.
- Test the flow: login, refresh, see welcome message, logout, see form again.
AI Prompts
Use these prompts with your AI tool to explore session concepts:
- "Write a PHP session demo that starts a session, stores a username, and displays it. Explain each line of code."
- "What are three security risks with PHP sessions, and how do I fix them? Show code examples."
- "Generate a PHP script that demonstrates session fixation attacks and how to prevent them with
session_regenerate_id()."
Starter Code
Create a file named session-demo.php:
Final Code
Exercises
- Modify the final code to store the user's favorite color in the session and display it after login.
- Add a counter that tracks how many times the user has refreshed the page during their session. Display the count on the page.
- Change the session cookie lifetime to 1 hour by setting
session.cookie_lifetime before session_start(). Test what happens when you close and reopen the browser within that hour.
Homework
- Research session hijacking. Write a short paragraph explaining what it is and list two ways to prevent it. Submit your answer as a comment in a new PHP file named
session-security.txt.
- Create a second page named
page2.php that requires a session. If the user is not logged in, redirect them back to session-demo.php. If they are logged in, display "You reached a protected page."
Quiz
- What does
session_start() do?
A) Starts a new session and loads existing session data
B) Deletes all session data
C) Sets a cookie without server-side storage
D) Logs the user into the website automatically
Answer: A
- Which superglobal array is used to access session data?
A) $_COOKIE
B) $_SESSION
C) $_SERVER
D) $_POST
Answer: B
- What function destroys all session data?
A) session_end()
B) session_stop()
C) session_destroy()
D) session_delete()
Answer: C
- Why is HTTP called stateless?
A) It cannot store files
B) Each request is independent and does not remember previous requests
C) It uses UDP instead of TCP
D) It only supports GET requests
Answer: B
- Where should
session_start() be placed in a PHP file?
A) At the very end of the file
B) After all HTML output
C) At the very top, before any HTML or whitespace
D) Inside the <body> tag
Answer: C
Lesson 2: Building Secure Login and Logout Forms
Duration: 1 hour 30 minutes
Learning Objectives
- Build a login form using HTML and PHP
- Validate form input on the server side
- Implement a logout button that securely ends the session
- Use prepared statements to query the database safely
- Test edge cases such as empty fields and SQL injection attempts
Instructor Notes
Login forms are the front door to an application. Emphasize that client-side validation is not enough; every input must be validated on the server. Remind students that AI tools sometimes skip server-side validation. Show how to inspect the network tab in browser dev tools to confirm form submission behavior.
Presentation Outline
- Login Form Anatomy (10 min)
HTML form elements
POST method vs GET method
Action attribute
- Database Setup (15 min)
Users table structure
Connecting to MySQL with PDO
- Processing Login Logic (20 min)
Retrieving submitted data
Validating inputs
Querying the database
- Logout Implementation (10 min)
Destroying the session
Redirecting after logout
- Testing and Debugging (15 min)
Common form errors
Using browser dev tools
Error reporting
Demonstration
Follow these steps to build a complete login/logout system:
- Create a database named
auth_demo and a table named users with columns: id, username, password_hash, and created_at.
- Insert one test user with a known password hash (you can generate one using
password_hash('secret', PASSWORD_DEFAULT)).
- Create
config.php to store database credentials and a PDO connection.
- Create
login.php with an HTML form that has username and password fields.
- At the top of
login.php, include config.php and start the session.
- Add server-side validation: check if both fields are filled, and show an error if not.
- Query the database using a prepared statement to find the user by username.
- If the user exists, use
password_verify() to check the submitted password against the stored hash.
- If verification succeeds, store the user ID and username in the session, then redirect to
dashboard.php.
- If verification fails, display an error message.
- Create
logout.php that destroys the session and redirects back to login.php.
- Add a logout button on
dashboard.php that links to logout.php.
AI Prompts
- "Write a PHP login script using PDO prepared statements. Include server-side validation for empty username and password fields. Add comments explaining each step."
- "Generate an HTML login form with labels, placeholder text, and basic CSS styling. The form should submit to a PHP file named login.php using the POST method."
- "Show me how to handle login errors in PHP. Display specific messages for empty fields, wrong username, and wrong password without revealing which one was wrong for security."
Starter Code
Create config.php:
Create login.php:
Create logout.php:
Final Code
config.php:
login.php:
logout.php:
dashboard.php:
Exercises
- Add client-side validation to the login form that checks if the username is at least 3 characters long before submitting.
- Create a "Remember Me" checkbox on the login form. When checked, store the username in a cookie that lasts for 7 days. On page load, if the cookie exists, auto-fill the username field.
- Modify the login error message so it does not reveal whether the username exists. Use a generic message for both invalid username and wrong password.
Homework
- Write a PHP script named
register.php with a registration form (username, password, confirm password). Store new users in the users table using a password hash. Redirect to login.php after successful registration.
- Add server-side validation to
register.php: check if the username already exists, ensure passwords match, and enforce a minimum password length of 6 characters.
Quiz
- Which HTTP method should a login form use to keep sensitive data out of the URL?
A) GET
B) POST
C) PUT
D) DELETE
Answer: B
- Why is
htmlspecialchars() used when echoing user input?
A) To encrypt the output
B) To prevent cross-site scripting (XSS) attacks
C) To make the text bold
D) To compress the HTML
Answer: B
- What does
password_verify() do?
A) Hashes a password for storage
B) Compares a plain password with a stored hash
C) Encrypts a password with AES
D) Generates a random password
Answer: B
- What is the purpose of
trim() on user input?
A) It removes whitespace from the beginning and end
B) It shortens the string to 10 characters
C) It converts the string to lowercase
D) It removes HTML tags
Answer: A
- After a successful login, what is the best way to prevent session fixation?
A) Call session_start() again
B) Call session_regenerate_id(true)
C) Delete the cookies
D) Change the database password
Answer: B
Lesson 3: Password Hashing and Security
Duration: 1 hour 15 minutes
Learning Objectives
- Explain why plain-text passwords are insecure
- Use
password_hash() to store passwords safely
- Use
password_verify() to check passwords
- Understand password hashing options and cost factors
- Identify common password security mistakes generated by AI
Instructor Notes
Students may ask why we do not use MD5 or SHA1. Explain that these are fast hashing algorithms designed for checksums, not password storage. Modern GPUs can crack them quickly. password_hash() uses bcrypt by default, which is intentionally slow. Show the AI a generated MD5 hashing example and ask it why that is bad for passwords.
Presentation Outline
- The Problem with Plain-Text Passwords (10 min)
What happens if a database is leaked
Real-world breach examples
- Hashing vs Encryption (15 min)
One-way hashing
Salting
Key differences
- PHP Password Functions (20 min)
password_hash()
password_verify()
password_needs_rehash()
- Cost Factor and Algorithm Options (15 min)
PASSWORD_DEFAULT vs PASSWORD_BCRYPT
Adjusting the cost
- Common AI Mistakes (5 min)
Demonstration
Follow these steps to explore password hashing:
- Create a new PHP file named
hash-demo.php.
- At the top, start the session and include
config.php.
- Create a simple form with one password field and a submit button.
- When the form is submitted, generate a hash using
password_hash() with the default options and display it.
- Below the hash, add a second form with a password field and a "Verify" button.
- When the second form is submitted, use
password_verify() to compare the input with the stored hash and display whether it matches.
- Change the cost factor to 12 and regenerate the hash. Observe how the hash length and format change.
- Show how
password_needs_rehash() returns true when the algorithm or cost has changed.
AI Prompts
- "Explain the difference between hashing and encrypting passwords. Show PHP code for both and explain why hashing is the correct choice for passwords."
- "Write a PHP script that hashes a password with a custom cost of 12, verifies it, and checks if it needs rehashing. Add comments explaining each output."
- "A student asks why MD5 is bad for passwords. Generate a clear explanation with a real-world analogy and a code example showing how fast MD5 can be cracked."
Starter Code
Create hash-demo.php:
Final Code
Exercises
- Modify the demo to accept a custom cost factor from the user (between 10 and 12). Display the time it takes to generate the hash using
microtime().
- Create a script that checks whether a given hash uses the bcrypt algorithm. Display the algorithm info using
password_get_info().
- Write a test that stores a password with cost 10, then checks
password_needs_rehash() after changing the default cost to 12. Show the output.
Homework
- Read about the PHP
password_hash() documentation on php.net. Write a one-page summary of the options parameter and when to use each algorithm.
- Create a script named
password-policy.php that enforces the following rules: minimum 8 characters, at least one uppercase letter, one lowercase letter, one number, and one special character. Display a specific error message for each rule that fails.
Quiz
- Which PHP function creates a password hash for storage?
A) md5()
B) sha1()
C) password_hash()
D) crypt()
Answer: C
- Which function checks if a plain password matches a stored hash?
A) password_check()
B) password_verify()
C) password_match()
D) password_compare()
Answer: B
- Why are MD5 and SHA1 not recommended for password hashing?
A) They are too long
B) They are too slow
C) They are fast and vulnerable to brute-force attacks
D) They are not supported by PHP
Answer: C
- What is the purpose of a salt in password hashing?
A) To make the hash longer
B) To add random data so identical passwords produce different hashes
C) To encrypt the password before hashing
D) To compress the hash
Answer: B
- What does
password_needs_rehash() check?
A) If the hash is corrupted
B) If the hash needs to be regenerated due to algorithm or cost changes
C) If the password is too short
D) If the user is an admin
Answer: B
Lesson 4: Protected Routes and Access Control
Duration: 1 hour
Learning Objectives
- Create reusable functions for route protection
- Redirect unauthenticated users to the login page
- Implement role-based access control (RBAC) basics
- Build a simple access control system using user roles
- Debug common routing issues caused by AI-generated code
Instructor Notes
Protected routes are essential for any application with private pages. Keep the examples simple: check for a session variable and redirect if missing. Introduce roles as a bonus concept so students see how to extend the system. Remind them to always exit after a header('Location: ...') redirect.
Presentation Outline
- What Are Protected Routes? (10 min)
Public vs private pages
Middleware concept simplified
- Building an Auth Helper (15 min)
Checking authentication status
Redirecting unauthenticated users
- Role-Based Access Control (15 min)
Adding a role column to the users table
Checking roles before allowing access
- Common Redirect Bugs (10 min)
Forgetting exit after header()
Output before session_start()
- Testing Routes (10 min)
Demonstration
Follow these steps to protect routes:
- Add a
role column to the users table with a default value of 'user'.
- Create
auth.php with two functions: require_login() and require_role($role).
require_login() checks if $_SESSION['user_id'] is set. If not, it redirects to login.php and exits.
require_role($role) checks if $_SESSION['role'] matches the required role. If not, it redirects to unauthorized.php.
- Create
admin.php that requires the admin role. Test with a regular user and an admin user.
- Create
unauthorized.php to display a friendly "Access Denied" message.
- Protect
dashboard.php with require_login() and observe the redirect behavior.
- Create a logout button on
dashboard.php that links to logout.php.
AI Prompts
- "Write a PHP file named auth.php with two functions: require_login() and require_role($role). Include comments explaining how to use them in other files."
- "Generate a protected admin page in PHP that redirects non-admin users to an unauthorized page. Show both the auth helper and the admin page code."
- "What are common bugs when using header('Location: ...') in PHP? List three and show how to fix them with code examples."
Starter Code
Create auth.php:
Create admin.php:
Create unauthorized.php:
Final Code
auth.php:
admin.php:
unauthorized.php:
Exercises
- Add a
require_guest() function to auth.php that redirects logged-in users away from the login page to dashboard.php. Use it on login.php.
- Create a
profile.php page that only the logged-in user can access. Add a check to ensure users can only view their own profile by comparing $_SESSION['user_id'] with a URL parameter id.
- Create an
editor.php page that accepts both admin and editor roles. Use an array of allowed roles in require_role() to simplify the check.
Homework
- Refactor
login.php from Lesson 2 to store the user's role in the session after login. Update the database query to fetch the role column.
- Create a navigation menu (
nav.php) that shows different links based on the user's login status and role. Include it on all protected pages using require_once.
Quiz
- What does the
exit statement do after a header('Location: ...') redirect?
A) It saves the session
B) It stops the script so the rest of the page does not load
C) It refreshes the page
D) It deletes the session
Answer: B
- Which function should you call at the top of every page that uses sessions?
A) session_create()
B) session_start()
C) session_init()
D) session_open()
Answer: B
- What is the purpose of role-based access control?
A) To speed up page loading
B) To restrict access based on the user's role
C) To encrypt the database
D) To compress images
Answer: B
- Why should you never trust user input for access control?
A) It is always encrypted
B) Users can manipulate URLs, cookies, and hidden fields
C) It slows down the server
D) It breaks CSS
Answer: B
- If a user is not logged in and visits
admin.php, what should happen?
A) They see an empty page
B) They are redirected to login.php
C) They are automatically logged in as admin
D) The server crashes
Answer: B
Module Summary
You have built a complete authentication system from scratch using PHP and MySQL. You learned how to manage sessions, create secure login forms, hash passwords, and protect routes. These skills are essential for any web application that handles user data.
Key Takeaways
- Always start sessions with
session_start() before any output.
- Never store plain-text passwords; use
password_hash() and password_verify().
- Always validate and sanitize user input on the server side.
- Use prepared statements to prevent SQL injection.
- Redirect and
exit after protecting a route.
- Verify AI output, especially for security-related code.
Next Steps
In Module 11, you will learn about APIs and how to build RESTful endpoints. You will use the authentication skills from this module to secure API routes.
Grading Rubric Reminder
| Criterion | Weight | |---|---| | Correctness | 40% | | Code readability and style | 20% | | Use of AI tools (prompts shown, output verified) | 20% | | Security awareness | 10% | | Documentation and comments | 10% |
الوحدة 10: المصادقة (Authentication)
الدورة: البرمجة بأدوات الذكاء الاصطناعي المجانية — بناء مواقع وتطبيقات حقيقية | الجمهور: أعمار 15–25، مبتدئون | هدف الوحدة: إضافة مصادقة آمنة لتطبيقات الويب: جلسات PHP، نماذج تسجيل الدخول، تجزئة كلمات المرور، وحماية الصفحات.
المبدأ الأساسي: تحقق دائماً من الكود المولد بالذكاء الاصطناعي، خاصة الكود المتعلق بالأمان.
الدرس 1: فهم الجلسات وأساسيات المصادقة
المدة: 1 ساعة 15 دقيقة
ملخّص: شرح المصادقة وكيف تعمل جلسات PHP، بدء وتدمير الجلسات بأمان، وبناء هيكل نظام تسجيل دخول.
الدرس 2: بناء نماذج تسجيل الدخول والخروج الآمنة
المدة: 1 ساعة 30 دقيقة
ملخّص: بناء نموذج login، التحقق من المدخلات، استخدام prepared statements، تنفيذ logout، واختبار الحالات الحدية.
الدرس 3: تجزئة كلمات المرور والأمان
المدة: 1 ساعة 15 دقيقة
ملخّص: شرح خطورة كلمات المرور النصية، استخدام password_hash() و password_verify()، فهم خوارزميات التجزئة وعوامل التكلفة.
الدرس 4: المسارات المحمية والتحكم بالوصول
المدة: 1 ساعة
ملخّص: إنشاء دوال لحماية المسارات، إعادة توجيه المستخدمين غير المسجلين، تنفيذ RBAC أساسي، وبناء نظام تحكم بالوصول.