0, 'path' => '/', 'secure' => $isHttps, 'httponly' => true, 'samesite' => 'Strict', ]); session_start(); } function csrf_token(): string { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } function csrf_field(): string { return ''; } function csrf_verify(?string $token): bool { return is_string($token) && $token !== '' && isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token); } // Logs the session out if the user's session_version has moved on since login (e.g. a // password reset bumped it), so a stolen/old session cookie stops working immediately // instead of staying valid until it naturally expires. Call this right after // start_app_session() + getDbConnection() on any page that trusts $_SESSION['user_id']. function enforce_session_version(PDO $pdo): void { if (!isset($_SESSION['user_id'])) { return; } $stmt = $pdo->prepare('SELECT session_version FROM users WHERE id = :id'); $stmt->execute(['id' => $_SESSION['user_id']]); $currentVersion = $stmt->fetchColumn(); $sessionVersionMatches = $currentVersion !== false && isset($_SESSION['session_version']) && (int) $currentVersion === (int) $_SESSION['session_version']; if (!$sessionVersionMatches) { $_SESSION = []; session_destroy(); } }