A "Remember Me" feature keeps users logged in across browser restarts by storing a long-lived authentication token in a cookie. Implementing it securely requires more than just extending the session lifetime.
Generate a cryptographically random token and store its hash in the database.
Store the raw token in a long-lived cookie.
On each request, look up the hashed token, validate it, and re-authenticate the user.
Rotate the token on each use (rolling tokens) to detect theft.
Example
<?php
// Pseudo-code — assumes $db is a PDO instance
function setRememberMe(int $userId, PDO $db): void
{
$token = bin2hex(random_bytes(32)); // 64-char hex token
$hash = hash('sha256', $token); // store hash, not raw token
$selector = bin2hex(random_bytes(6)); // short identifier to look up row
// Store selector + hash in DB with expiry (30 days)
$db->prepare('INSERT INTO remember_tokens (selector, hash, user_id, expires_at)
VALUES (?, ?, ?, ?)')
->execute([$selector, $hash, $userId, date('Y-m-d H:i:s', time() + 86400 * 30)]);
// Send selector:token in cookie
setcookie('remember', $selector . ':' . $token, [
'expires' => time() + 86400 * 30,
'path' => '/',
'httponly' => true,
'secure' => true,
'samesite' => 'Lax',
]);
}
function loginFromRememberMe(PDO $db): ?int
{
if (empty($_COOKIE['remember'])) return null;
[$selector, $token] = explode(':', $_COOKIE['remember'], 2) + ['', ''];
$row = $db->prepare('SELECT * FROM remember_tokens WHERE selector = ? AND expires_at > NOW()')
->execute([$selector]) ? null : null; // simplified
if (!$row || !hash_equals($row['hash'], hash('sha256', $token))) {
return null; // invalid or stolen
}
// Rotate token
setRememberMe($row['user_id'], $db);
$db->prepare('DELETE FROM remember_tokens WHERE selector = ?')->execute([$selector]);
return (int) $row['user_id'];
}
Pro Tip
Tip: Use a selector:token split. The selector (stored plain) identifies the database row without a full-table scan. The token (stored as a hash) is the secret. This limits damage if the database is breached — attackers get hashes, not valid tokens.