Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- // 4o-mini-high
- /**
- * @file AuthController.php
- * @description Handles HTTP requests for authentication. It processes user input,
- * manages CSRF tokens, and interacts with the AuthService to perform
- * the actual login logic. It is responsible for redirects and rendering views.
- *
- * @version 1.0.0
- * @since 2025-07-25
- * @author Barrac0de
- */
- declare(strict_types=1);
- namespace App\Auth;
- use PDO;
- use RuntimeException;
- require_once __DIR__ . '/config.php';
- require_once __DIR__ . '/AuthService.php';
- class AuthController
- {
- private AuthService $authService;
- private string $basePath;
- private int $timeoutDuration = 3600; // session inactivity timeout
- public function __construct(PDO $pdo)
- {
- $this->authService = new AuthService($pdo);
- // ensure BASE_PATH ends with a slash
- $this->basePath = defined('BASE_PATH')
- ? rtrim(BASE_PATH, '/') . '/'
- : '/';
- }
- public function run(): void
- {
- $this->startSession();
- $this->sendSecurityHeaders();
- if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- $this->showLoginForm();
- } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $this->processLogin();
- } else {
- http_response_code(405);
- exit;
- }
- }
- private function startSession(): void
- {
- ini_set('session.use_strict_mode', '1');
- if (session_status() === PHP_SESSION_NONE) {
- ini_set('session.cookie_httponly', '1');
- ini_set('session.cookie_secure', '1');
- ini_set('session.cookie_samesite', 'Lax');
- session_start();
- }
- }
- private function sendSecurityHeaders(): void
- {
- header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
- header('X-Frame-Options: DENY');
- header('X-Content-Type-Options: nosniff');
- header('Referrer-Policy: no-referrer');
- header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';");
- }
- private function showLoginForm(): void
- {
- // if already logged in, go to dashboard
- if (!empty($_SESSION['user_id'])) {
- header('Location: ' . $this->basePath . 'index');
- exit;
- }
- // pull flash data
- $error = $_SESSION['login_error'] ?? '';
- $oldUsername = $_SESSION['old_username'] ?? '';
- unset($_SESSION['login_error'], $_SESSION['old_username']);
- // ensure CSRF token
- if (empty($_SESSION['csrf_token'])) {
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- }
- require __DIR__ . '/../login.php';
- exit;
- }
- private function processLogin(): void
- {
- // session inactivity timeout
- if (isset($_SESSION['last_activity'])
- && (time() - $_SESSION['last_activity']) > $this->timeoutDuration
- ) {
- session_unset();
- session_destroy();
- header('Location: ' . $this->basePath . 'login?timeout=1');
- exit;
- }
- $_SESSION['last_activity'] = time();
- // CSRF check
- $csrfToken = filter_input(INPUT_POST, 'csrf_token', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
- if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrfToken)) {
- $this->bounce('Invalid CSRF token.');
- }
- // sanitize inputs
- $username = trim((string)filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
- $password = (string)filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
- if ($username === '' || $password === '') {
- $this->bounce('Username and password are required.');
- }
- // attempt authentication
- try {
- $userId = $this->authService->authenticate($username, $password);
- } catch (RuntimeException $e) {
- $this->bounce($e->getMessage());
- }
- // on success
- session_regenerate_id(true);
- $_SESSION['user_id'] = $userId;
- // rotate CSRF
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- header('Location: ' . $this->basePath . 'index');
- exit;
- }
- private function bounce(string $message): void
- {
- // preserve username for UX
- $old = trim((string)filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
- $_SESSION['old_username'] = $old;
- $_SESSION['login_error'] = $message;
- header('Location: ' . $this->basePath . 'login');
- exit;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment