PHP 8: Modern PHP Development · Security for PHP Applications
Passwords and Authentication
Hash passwords with password_hash, verify them safely and rehash as algorithms improve.
Never store plain or reversibly encrypted passwords. Use password_hash() with PASSWORD_DEFAULT (bcrypt today) or PASSWORD_ARGON2ID, verify with password_verify() (constant-time), and call password_needs_rehash() after login to upgrade hashes when cost or algorithm changes. Rate-limit login attempts, return generic error messages, and regenerate the session ID after login.
<?php
$hash = password_hash($plainPassword, PASSWORD_ARGON2ID);
function login(UserRepository $users, string $email, #[\SensitiveParameter] string $password): ?User
{
$user = $users->findByEmail($email);
if ($user === null || !password_verify($password, $user->passwordHash)) {
return null; // same response for both cases
}
if (password_needs_rehash($user->passwordHash, PASSWORD_ARGON2ID)) {
$user->passwordHash = password_hash($password, PASSWORD_ARGON2ID);
$users->save($user);
}
session_regenerate_id(true);
$_SESSION['user_id'] = $user->id;
return $user;
}
Common pitfalls
- Using
md5()/sha1()or a single SHA-256 for passwords. - Different error messages for unknown email vs wrong password (account enumeration).
- Not regenerating the session ID at login (session fixation).
Key points
- password_hash / password_verify
- Rehash when algorithms change
- Regenerate session IDs on login
Further reading: PHP manual: password_hash
Practice questions
Why is password_verify() preferred over comparing hashes with ===?
Answer
It extracts the algorithm, cost and salt from the stored hash, recomputes correctly, and compares in constant time. Manual comparison is error-prone and may leak timing information.
What does password_needs_rehash() enable?
Answer
Transparent upgrades: after a successful login you can rehash the known plain password with the current algorithm/cost and save it.
Open in the app to mark lessons complete, take notes and track your progress.