widimulcing

AuthController.php

Jul 29th, 2025
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.12 KB | None | 0 0
  1. <?php
  2. // Gemini 2.5 pro
  3.  
  4. /**
  5.  * @file        AuthController.php
  6.  * @description Handles HTTP requests for authentication. It processes user input,
  7.  * manages CSRF tokens, and interacts with the AuthService to perform
  8.  * the actual login logic. It is responsible for redirects and rendering views.
  9.  *
  10.  * @version     1.0.0
  11.  * @since       2025-07-25
  12.  * @author      Barrac0de
  13.  */
  14. declare(strict_types=1);
  15.  
  16. namespace App\Auth;
  17.  
  18. use App\Auth\AuthService;
  19.  
  20. class AuthController
  21. {
  22.     private AuthService $authService;
  23.  
  24.     public function __construct(AuthService $authService)
  25.     {
  26.         $this->authService = $authService;
  27.     }
  28.  
  29.     /**
  30.      * Handles the incoming web request and routes it to the appropriate method.
  31.      */
  32.     public function handleRequest(): void
  33.     {
  34.         if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  35.             $this->processLogin();
  36.         } else {
  37.             $this->showLoginForm();
  38.         }
  39.     }
  40.  
  41.     /**
  42.      * Displays the login form, handles flash messages, and sets a CSRF token.
  43.      */
  44.     public function showLoginForm(): void
  45.     {
  46.         // Redirect if already authenticated
  47.         if (isset($_SESSION['user_id'])) {
  48.             header('Location: ' . BASE_PATH . 'index');
  49.             exit;
  50.         }
  51.  
  52.         // Prepare variables for the view
  53.         $error = $_SESSION['login_error'] ?? '';
  54.         $oldUsername = $_SESSION['old_username'] ?? '';
  55.         unset($_SESSION['login_error'], $_SESSION['old_username']);
  56.  
  57.         // Generate CSRF token if it doesn't exist
  58.         if (empty($_SESSION['csrf_token'])) {
  59.             $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
  60.         }
  61.         $csrfToken = $_SESSION['csrf_token'];
  62.  
  63.         // Expose variables and render the view
  64.         require __DIR__ . '/../views/login.php'; // Assuming your view is in a 'views' folder
  65.         exit;
  66.     }
  67.  
  68.     /**
  69.      * Processes the login submission from the POST request.
  70.      */
  71.     public function processLogin(): void
  72.     {
  73.         // CSRF protection
  74.         $csrfToken = filter_input(INPUT_POST, 'csrf_token', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
  75.         if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrfToken)) {
  76.             $this->bounce('Invalid CSRF token.');
  77.         }
  78.  
  79.         // Input sanitization
  80.         $username = trim((string)filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
  81.         $password = (string)filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
  82.  
  83.         if ($username === '' || $password === '') {
  84.             $this->bounce('Username and password are required.');
  85.         }
  86.        
  87.         // Let the service handle the core logic
  88.         $result = $this->authService->attemptLogin($username, $password);
  89.  
  90.         if ($result['success']) {
  91.             $this->handleSuccessfulLogin($result['user_id']);
  92.         } else {
  93.             $this->bounce($result['message']);
  94.         }
  95.     }
  96.  
  97.     /**
  98.      * Handles a successful login by regenerating session and redirecting.
  99.      * @param int $userId The ID of the logged-in user.
  100.      */
  101.     private function handleSuccessfulLogin(int $userId): void
  102.     {
  103.         // Regenerate session ID to prevent session fixation
  104.         session_regenerate_id(true);
  105.         $_SESSION['user_id'] = $userId;
  106.         $_SESSION['last_activity'] = time();
  107.  
  108.         // Rotate CSRF token on successful login
  109.         $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
  110.  
  111.         header('Location: ' . BASE_PATH . 'index');
  112.         exit;
  113.     }
  114.  
  115.     /**
  116.      * Set flash error, preserve attempted username, and redirect back to login.
  117.      * @param string $message The error message to display.
  118.      */
  119.     private function bounce(string $message): void
  120.     {
  121.         // Preserve the last entered username for better UX
  122.         $old = trim((string) filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
  123.         if ($old) {
  124.             $_SESSION['old_username'] = $old;
  125.         }
  126.        
  127.         $_SESSION['login_error'] = $message;
  128.         header('Location: ' . BASE_PATH . 'login');
  129.         exit;
  130.     }
  131. }
  132.  
Advertisement
Add Comment
Please, Sign In to add comment