Dragon-Knight/src/auth.php

105 lines
2.8 KiB
PHP
Raw Normal View History

2024-12-17 22:10:49 -06:00
<?php
/*
This is an experimental new class for handling user auth. The idea is to rely as much as possible on PHP's native
session handling. When authenticated, the class will store use data in GLOBALS state.
*/
class Auth
{
/**
* Set up the auth manager; adjust PHP session settings on the fly to improve security. Starts the session for
* this request.
*/
public function __construct()
{
// enhance the native session's sessid cryptography
ini_set('session.sid_length', 64);
ini_set('session.sid_bits_per_character', 6);
session_set_cookie_params([
'lifetime' => 2592000, // 30 days
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
session_start();
$this->validate();
}
private function validate(): void
{
// Check for IP address change
if (!isset($_SESSION['ip_address'])) {
$_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
} elseif ($_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR']) {
$this->destroy(); // Possible hijacking
exit;
}
// Check for User-Agent change
if (!isset($_SESSION['user_agent'])) {
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
} elseif ($_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) {
$this->destroy(); // Possible hijacking
exit;
}
// Regenerate session ID periodically for security
if (!isset($_SESSION['last_regeneration'])) {
$_SESSION['last_regeneration'] = time();
} elseif (time() - $_SESSION['last_regeneration'] > 300) { // Every 5 minutes
$this->regenerate();
}
}
public function login(string $username, string $password): bool
{
$user = get_user($username);
if ($user === false) return false;
if (password_verify($password, $user['password'])) {
$_SESSION['authenticated'] = true;
$_SESSION['user_id'] = $user['id'];
$_SESSION['login_time'] = time();
$this->regenerate();
return true;
}
return false;
}
public function good(): bool
{
return isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true;
}
public function logout(): void
{
$this->destroy();
}
private function regenerate(): void
{
session_regenerate_id(true);
$_SESSION['last_regeneration'] = time();
}
public function destroy(): void
{
$_SESSION = [];
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
session_destroy();
}
}