widimulcing

AuthController.php

Jul 29th, 2025
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.50 KB | None | 0 0
  1. <?php
  2. // Claude Sonnet
  3. /**
  4.  * @file        AuthController.php
  5.  * @description Handles login requests securely with session, CSRF, and redirect handling.
  6.  *              This controller processes user login and manages session regeneration and flash errors.
  7.  *
  8.  * @version     1.0.0
  9.  * @since       2025-07-29
  10.  * @author      Barrac0de
  11.  */
  12. declare(strict_types=1);
  13.  
  14. namespace App\Auth;
  15.  
  16. use PDO;
  17.  
  18. require_once __DIR__ . '/../../config.php';
  19. require_once __DIR__ . '/AuthService.php';
  20.  
  21. class AuthController
  22. {
  23.     /** @var PDO */
  24.     private $pdo;
  25.    
  26.     /** @var AuthService */
  27.     private $authService;
  28.    
  29.     /** @var int */
  30.     private $sessionTimeout = 3600; // 1 hour
  31.  
  32.     /**
  33.      * Constructor
  34.      *
  35.      * @param PDO $pdo Database connection
  36.      */
  37.     public function __construct(PDO $pdo)
  38.     {
  39.         $this->pdo = $pdo;
  40.         $this->authService = new AuthService($pdo);
  41.        
  42.         // Enforce strict session ID handling
  43.         ini_set('session.use_strict_mode', '1');
  44.         if (session_status() === PHP_SESSION_NONE) {
  45.             ini_set('session.cookie_httponly', '1');
  46.             ini_set('session.cookie_secure',   '1');
  47.             ini_set('session.cookie_samesite', 'Lax');
  48.             session_start();
  49.         }
  50.        
  51.         // Security headers
  52.         header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
  53.         header('X-Frame-Options: DENY');
  54.         header('X-Content-Type-Options: nosniff');
  55.         header('Referrer-Policy: no-referrer');
  56.         header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';");
  57.     }
  58.  
  59.     /**
  60.      * Handle the login request
  61.      */
  62.     public function handleRequest()
  63.     {
  64.         // Redirect if database connection failed
  65.         if (!isset($this->pdo) || !($this->pdo instanceof PDO)) {
  66.             http_response_code(500);
  67.             exit('Database connection failed.');
  68.         }
  69.  
  70.         // Check session timeout
  71.         $this->checkSessionTimeout();
  72.  
  73.         if ($_SERVER['REQUEST_METHOD'] === 'GET') {
  74.             $this->handleGetRequest();
  75.         } else {
  76.             $this->handlePostRequest();
  77.         }
  78.     }
  79.  
  80.     /**
  81.      * Handle GET requests for the login page
  82.      */
  83.     private function handleGetRequest()
  84.     {
  85.         // Redirect if already authenticated
  86.         if (isset($_SESSION['user_id'])) {
  87.             header('Location: ' . BASE_PATH . 'index');
  88.             exit;
  89.         }
  90.  
  91.         // Flash error and old username
  92.         $error = $_SESSION['login_error'] ?? '';
  93.         $oldUsername = $_SESSION['old_username'] ?? '';
  94.         unset($_SESSION['login_error'], $_SESSION['old_username']);
  95.  
  96.         // CSRF token
  97.         if (empty($_SESSION['csrf_token'])) {
  98.             $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
  99.         }
  100.  
  101.         // Expose view variables
  102.         require __DIR__ . '/../../login.php';
  103.         exit;
  104.     }
  105.  
  106.     /**
  107.      * Handle POST requests for login form submission
  108.      */
  109.     private function handlePostRequest()
  110.     {
  111.         // CSRF protection
  112.         $csrfToken = filter_input(INPUT_POST, 'csrf_token', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
  113.         if (empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $csrfToken)) {
  114.             $this->authService->bounce('Invalid CSRF token.');
  115.         }
  116.  
  117.         // Input sanitization
  118.         $username = trim((string)filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
  119.         $password = (string)filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
  120.  
  121.         // Authenticate user
  122.         $user = $this->authService->authenticate($username, $password);
  123.        
  124.         if ($user) {
  125.             // Login success
  126.             session_regenerate_id(true);
  127.             $_SESSION['user_id'] = $user['id'];
  128.            
  129.             // Rotate CSRF token
  130.             $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
  131.            
  132.             header('Location: ' . BASE_PATH . 'index');
  133.             exit;
  134.         }
  135.     }
  136.  
  137.     /**
  138.      * Check for session timeout and handle accordingly
  139.      */
  140.     private function checkSessionTimeout()
  141.     {
  142.         $_SESSION['last_activity'] = time();
  143.        
  144.         if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity']) > $this->sessionTimeout) {
  145.             session_unset();
  146.             session_destroy();
  147.             header('Location: ' . BASE_PATH . 'login?timeout=1');
  148.             exit;
  149.         }
  150.     }
  151. }
Advertisement
Add Comment
Please, Sign In to add comment