When using the old fashioned sha/md5 salted password hashing, you could store the username and password in a session e.g.
$_SESSION['username'] = $_POST['username'];
$_SESSION['password'] = sha1($salt . $_POST['password']);
The advantage of this is that on every request you can query the database WHERE username= :username AND password = :password'
where the variables come from the session. If the account is deleted or the password is changed, the user is logged out. Any user who thinks their account is compromised can change their password any anyone else using the account is logged out.
With password_verify
this is quite difficult because it’s a boolean operation. It’s possible to do it like this:
$_SESSION['username'] = $_POST['username'];
$_SESSION['password'] = $_POST['password'];
if (password_verify($_SESSION['password'], $hashFromDatabase)) {
//logged in
}
else {
//destroy session and forward to error/login page
}
While this works, it requires storing the password in plaintext in the session. The only way I can see to avoid this is hashing passwords twice. So instead of
$hashedPass = password_hash($_POST['password'], PASSWORD_DEFAULT);
You’d have:
$hashedPass = password_hash(sha1($_POST['password']), PASSWORD_DEFAULT);
That way, when someone logs in you can use $_SESSION['password'] = sha1($_POST['password']);
and then pass that to password_verify
.
Alternatively, extract the hash from the database and store it in the session, checking the old hash vs the new hash on every page load e.g on login:
if (password_verify($_POST['password'], $hashFromDatabase)) {
$_SESSION['username'] = $usernameFromDatabase;
$_SESSION['password'] = $hashFromDatabase;
}
and then on each request:
$user = $pdo->query('SELECT password FROM users WHERE username = ' . $_SESSION['username']);
if ($user->password != $_SESSION['password']) {
//password has been changed, log out.
}
This seems very long winded, is there a more efficient way to do this while maintaining the feature where changing the password causes other browsers to be logged out and not storing the plaintext password in a session?