Authentication
debt(d8/e6/b7/t7)
Closest to 'silent in production until users hit it' (d9), slightly better at d8 because SAST tools and security scanners (no detection_hints provided, but category-appropriate tools like Psalm taint analysis, SonarQube security rules) can flag weak hashing like MD5, but missing session_regenerate_id, missing rate limiting, and missing cookie flags are typically silent in production until exploited.
Closest to 'cross-cutting refactor across the codebase' (e7), slightly better at e6 because while quick_fix lists single-call swaps (password_hash, session_regenerate_id), in practice fixing authentication touches the login flow, registration, password reset, session config, and rate limiting middleware — multiple files across the auth subsystem.
Closest to 'strong gravitational pull' (b7), because authentication applies across web and CLI contexts and every protected endpoint depends on the auth model; changing the hashing algorithm or session strategy ripples through the entire application.
Closest to 'serious trap' (t7), grounded in the misconception field: developers reasonably believe storing a user ID in $_SESSION is sufficient, but the working-but-exploitable nature (missing cookie_secure, cookie_httponly, session_regenerate_id, timeout) is a classic case where the obvious implementation looks correct and passes tests but is broken in adversarial conditions.
Also Known As
TL;DR
Explanation
Authentication answers 'who is this user?' — distinct from authorisation ('what can they do?'). PHP authentication typically uses one of three mechanisms: session-based (credentials validated, user ID stored in a server-side session, session ID sent as a cookie); token-based (JWT or opaque token issued on login, sent in Authorization header on subsequent requests, validated server-side); or OAuth/OIDC (delegated to a third party like Google, GitHub, or an identity provider). Critical implementation requirements: passwords must be hashed with password_hash() using PASSWORD_ARGON2ID or PASSWORD_BCRYPT (never MD5 or SHA); login forms must use HTTPS; brute-force protection (rate limiting, account lockout) must be in place; session IDs must be regenerated on privilege change (session_regenerate_id(true)) to prevent session fixation. Laravel Sanctum handles API token authentication; Laravel Breeze/Jetstream handle session-based authentication.
Common Misconception
Why It Matters
Common Mistakes
- Using MD5 or SHA-1 for password hashing — use password_hash($pass, PASSWORD_ARGON2ID) exclusively.
- Not regenerating the session ID after login — session_regenerate_id(true) prevents session fixation attacks.
- Missing brute-force protection — without rate limiting, an attacker can try millions of passwords against any login endpoint.
- Storing plaintext passwords or reversibly encrypted passwords — if the database is compromised, all passwords are exposed immediately.
Code Examples
// MD5 hashing + no session regeneration + SQL injection
$hash = md5($_POST['password']); // crackable in seconds
$user = $db->query("SELECT * FROM users WHERE email='{$_POST['email']}'
AND password='$hash'"); // SQL injectable
if ($user) {
$_SESSION['user_id'] = $user['id'];
// No session_regenerate_id — session fixation possible
}
// Secure authentication
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$_POST['email']]);
$user = $stmt->fetch();
if ($user && password_verify($_POST['password'], $user['password_hash'])) {
session_regenerate_id(true); // prevent session fixation
$_SESSION['user_id'] = $user['id'];
$_SESSION['logged_in_at'] = time();
// Redirect — never re-display login form on success
header('Location: /dashboard');
exit;
}