2025-08-14 13:55:37 -04:00

115 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
/*
* This file is a part of the Dragon-Knight project.
*
* Copyright (c) 2024-present Sharkk
*
* This file is subject to the MIT license that is bundled
* with this source code in the LICENSE.md file.
*/
namespace DragonKnight;
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 = Lib::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();
}
}