Creating a user authentication system is a fundamental skill for any web developer. Whether you’re building a blog, an e-commerce platform, or a personal project, allowing users to sign up, sign in, and stay logged in with a “Remember Me” option is a must-have feature. In this article, we’ll walk you through the process of building a signup and sign-in system in PHP from scratch, complete with a “Remember Me” functionality, while keeping security and usability in mind. Let’s get started!
What You’ll Need
Before we begin, ensure you have:
- A local server setup (e.g., XAMPP, WAMP, or MAMP) with PHP and MySQL installed.
- Basic knowledge of HTML, CSS, PHP, and MySQL.
- A code editor (like VS Code or Sublime Text).
Step 1: Setting Up the Database
Every authentication system needs a place to store user data. We’ll use MySQL to create a database and a table for users.
Create the Database: Open your MySQL client (e.g., phpMyAdmin) and run:sql
CREATE DATABASE user_auth; USE user_auth;
Create the Users Table: We’ll store the user’s email, password, and a token for the “Remember Me” feature.sql
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, remember_token VARCHAR(100) NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
id: Unique identifier for each user.
email: User’s email (unique).
password: Hashed password for security.
remember_token: A random token for the “Remember Me” feature.
Step 2: Building the Signup System
Let’s create a form for users to sign up and a PHP script to process it.
Signup Form (signup.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Signup</title>
<style>
body { font-family: Arial, sans/CT; }
.container { width: 300px; margin: 50px auto; }
input { width: 100%; padding: 8px; margin: 5px 0; }
button { padding: 10px; background-color: #28a745; color: white; border: none; }
</style>
</head>
<body>
<div class="container">
<h2>Sign Up</h2>
<form action="signup.php" method="POST">
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Sign Up</button>
</form>
</div>
</body>
</html>
Signup Processing (signup.php):
<?php
// Database connection
$conn = new mysqli("localhost", "root", "", "user_auth");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL);
$password = password_hash($_POST["password"], PASSWORD_BCRYPT); // Hash the password
// Check if email already exists
$check = $conn->prepare("SELECT email FROM users WHERE email = ?");
$check->bind_param("s", $email);
$check->execute();
$check->store_result();
if ($check->num_rows > 0) {
echo "Email already exists!";
} else {
// Insert new user
$stmt = $conn->prepare("INSERT INTO users (email, password) VALUES (?, ?)");
$stmt->bind_param("ss", $email, $password);
if ($stmt->execute()) {
echo "Signup successful! <a href='signin.html'>Sign in here</a>";
} else {
echo "Error: " . $conn->error;
}
$stmt->close();
}
$check->close();
}
$conn->close();
?>
We sanitize the email and hash the password using password_hash() for security.
Prepared statements prevent SQL injection.
Step 3: Building the Sign-In System
Now, let’s create the sign-in form and logic, including the “Remember Me” option.
Sign-In Form (signin.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign In</title>
<style>
body { font-family: Arial, sans-serif; }
.container { width: 300px; margin: 50px auto; }
input { width: 100%; padding: 8px; margin: 5px 0; }
button { padding: 10px; background-color: #007bff; color: white; border: none; }
</style>
</head>
<body>
<div class="container">
<h2>Sign In</h2>
<form action="signin.php" method="POST">
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<label><input type="checkbox" name="remember"> Remember Me</label>
<button type="submit">Sign In</button>
</form>
</div>
</body>
</html>
Sign-In Processing (signin.php):
<?php
session_start();
$conn = new mysqli("localhost", "root", "", "user_auth");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL);
$password = $_POST["password"];
$remember = isset($_POST["remember"]);
// Verify user
$stmt = $conn->prepare("SELECT id, password FROM users WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $hashed_password);
$stmt->fetch();
if (password_verify($password, $hashed_password)) {
$_SESSION["user_id"] = $id; // Store user ID in session
// Handle "Remember Me"
if ($remember) {
$token = bin2hex(random_bytes(50)); // Generate a secure random token
setcookie("remember_me", $token, time() + (30 * 24 * 60 * 60), "/"); // 30 days
$update = $conn->prepare("UPDATE users SET remember_token = ? WHERE id = ?");
$update->bind_param("si", $token, $id);
$update->execute();
$update->close();
}
header("Location: dashboard.php");
exit();
} else {
echo "Incorrect password!";
}
} else {
echo "Email not found!";
}
$stmt->close();
}
$conn->close();
?>
password_verify() checks the password against the stored hash.
If “Remember Me” is checked, a random token is generated and stored in a cookie and the database.
Step 4: Implementing the “Remember Me” Feature
The “Remember Me” feature allows users to stay logged in even after closing the browser. Here’s how to check it:
Check Token on Page Load (dashboard.php):
<?php
session_start();
$conn = new mysqli("localhost", "root", "", "user_auth");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Check session first
if (!isset($_SESSION["user_id"])) {
// Check cookie if session is not set
if (isset($_COOKIE["remember_me"])) {
$token = $_COOKIE["remember_me"];
$stmt = $conn->prepare("SELECT id FROM users WHERE remember_token = ?");
$stmt->bind_param("s", $token);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id);
$stmt->fetch();
$_SESSION["user_id"] = $id; // Log the user in
}
$stmt->close();
} else {
header("Location: signin.html"); // Redirect to sign-in if no session or cookie
exit();
}
}
echo "Welcome to your dashboard!";
echo "<br><a href='logout.php'>Logout</a>";
$conn->close();
?>
Logout Script (logout.php):
<?php
session_start();
$conn = new mysqli("localhost", "root", "", "user_auth");
if (isset($_SESSION["user_id"])) {
$id = $_SESSION["user_id"];
// Clear the remember token
$stmt = $conn->prepare("UPDATE users SET remember_token = NULL WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->close();
// Clear cookie and session
setcookie("remember_me", "", time() - 3600, "/");
session_destroy();
}
$conn->close();
header("Location: signin.html");
exit();
?>
Step 5: Security Tips
- Use HTTPS: Always deploy your site with SSL to encrypt data.
- Validate Inputs: Add more robust input validation (e.g., password strength).
- Rate Limiting: Prevent brute-force attacks by limiting login attempts.
- Token Expiry: Add an expiration date to the “remember_token” in the database.
Conclusion
You’ve now built a fully functional signup and sign-in system in PHP with a “Remember Me” feature! This system securely handles user registration, login, and persistent sessions using cookies and tokens. Feel free to enhance it by adding features like password reset, email verification, or a more polished UI. With this foundation, you’re ready to integrate authentication into any PHP project.