Adding Authentication
Implement secure user registration and login
Add user authentication to your app with secure password hashing, sessions, and protected routes.
What You'll Build
A complete authentication system with:
- User registration with validation
- Secure login with password verification
- Session-based authentication
- Protected routes with Auth middleware
- Logout functionality
Time Required: 25-35 minutes
Step 1: Users Table Already Exists
DALT.PHP comes with a users table migration. Check if it's already run:
# Check if users table exists
php artisan migrateIf not already created, the migration creates:
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Step 2: Create Auth Controllers
Create Directory
mkdir -p app/Http/controllers/authRegister Form (GET /register)
Create app/Http/controllers/auth/register.php:
<?php
view('auth/register.view.php', [
'title' => 'Register'
]);Register Handler (POST /register)
Create app/Http/controllers/auth/register-post.php:
<?php
$db = App::resolve(Core\Database::class);
// Validate
$errors = [];
if (empty($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Valid email is required';
}
if (empty($_POST['password']) || strlen($_POST['password']) < 8) {
$errors['password'] = 'Password must be at least 8 characters';
}
if ($_POST['password'] !== $_POST['password_confirmation']) {
$errors['password_confirmation'] = 'Passwords do not match';
}
// Check if email exists
$existing = $db->query('SELECT id FROM users WHERE email = ?', [$_POST['email']])->find();
if ($existing) {
$errors['email'] = 'Email already registered';
}
if (!empty($errors)) {
view('auth/register.view.php', ['errors' => $errors, 'old' => $_POST]);
exit;
}
// Hash password and create user
$db->query(
'INSERT INTO users (email, password) VALUES (?, ?)',
[$_POST['email'], password_hash($_POST['password'], PASSWORD_BCRYPT)]
);
// Auto-login after registration
$user = $db->query('SELECT * FROM users WHERE email = ?', [$_POST['email']])->find();
Core\Session::put('user', ['id' => $user['id'], 'email' => $user['email']]);
Core\Session::flash('success', 'Account created successfully!');
header('Location: /');
exit;Login Form (GET /login)
Create app/Http/controllers/auth/login.php:
<?php
view('auth/login.view.php', [
'title' => 'Login'
]);Login Handler (POST /login)
Create app/Http/controllers/auth/login-post.php:
<?php
$db = App::resolve(Core\Database::class);
// Find user
$user = $db->query('SELECT * FROM users WHERE email = ?', [$_POST['email']])->find();
// Verify password
if (!$user || !password_verify($_POST['password'], $user['password'])) {
view('auth/login.view.php', [
'errors' => ['email' => 'Invalid credentials'],
'old' => $_POST
]);
exit;
}
// Create session
Core\Session::put('user', ['id' => $user['id'], 'email' => $user['email']]);
Core\Session::flash('success', 'Welcome back!');
header('Location: /');
exit;Logout Handler (POST /logout)
Create app/Http/controllers/auth/logout.php:
<?php
Core\Session::destroy();
Core\Session::flash('success', 'Logged out successfully');
header('Location: /');
exit;Step 3: Create Views
Register View
Create resources/views/auth/register.view.php:
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
</head>
<body>
<h1>Register</h1>
<form method="POST" action="/register">
<div>
<label>Email:</label>
<input type="email" name="email" value="<?= htmlspecialchars($old['email'] ?? '') ?>" required>
<?php if (isset($errors['email'])): ?>
<p style="color: red;"><?= $errors['email'] ?></p>
<?php endif; ?>
</div>
<div>
<label>Password:</label>
<input type="password" name="password" required>
<?php if (isset($errors['password'])): ?>
<p style="color: red;"><?= $errors['password'] ?></p>
<?php endif; ?>
</div>
<div>
<label>Confirm Password:</label>
<input type="password" name="password_confirmation" required>
<?php if (isset($errors['password_confirmation'])): ?>
<p style="color: red;"><?= $errors['password_confirmation'] ?></p>
<?php endif; ?>
</div>
<button type="submit">Register</button>
</form>
<p>Already have an account? <a href="/login">Login</a></p>
</body>
</html>Login View
Create resources/views/auth/login.view.php:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form method="POST" action="/login">
<div>
<label>Email:</label>
<input type="email" name="email" value="<?= htmlspecialchars($old['email'] ?? '') ?>" required>
</div>
<div>
<label>Password:</label>
<input type="password" name="password" required>
</div>
<?php if (isset($errors['email'])): ?>
<p style="color: red;"><?= $errors['email'] ?></p>
<?php endif; ?>
<button type="submit">Login</button>
</form>
<p>Don't have an account? <a href="/register">Register</a></p>
</body>
</html>Step 4: Add Routes
Add auth routes to routes/routes.php:
// Auth routes
$router->get('/register', 'auth/register.php')->only('guest');
$router->post('/register', 'auth/register-post.php')->only('guest');
$router->get('/login', 'auth/login.php')->only('guest');
$router->post('/login', 'auth/login-post.php')->only('guest');
$router->post('/logout', 'auth/logout.php')->only('auth');Step 5: Protect Routes
Protect routes that require authentication:
// Protected routes
$router->get('/dashboard', 'dashboard.php')->only('auth');
$router->get('/posts/create', 'posts/create.php')->only('auth');
$router->post('/posts', 'posts/store.php')->only('auth');Step 6: Test Authentication
Start Server
php artisan serveRegister a User
- Visit http://localhost:8000/register
- Enter email and password
- Click Register
- You should be logged in automatically
Logout
Add logout button to your views:
<?php if (Core\Session::has('user')): ?>
<form method="POST" action="/logout" style="display: inline;">
<button type="submit">Logout</button>
</form>
<?php endif; ?>Login Again
- Visit http://localhost:8000/login
- Enter your credentials
- Click Login
Security Notes
Your authentication uses bcrypt password hashing, email validation, session-based auth, and middleware protection. Always use htmlspecialchars() when displaying user data to prevent XSS.
What's Next
You've implemented secure authentication with password hashing and protected routes. From here you can add password reset, remember me functionality, or two-factor authentication.
Done! You now understand authentication, password security, and route protection.