Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- // Gemini 2.5 pro
- /**
- * @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 App\Auth\AuthService;
- class AuthController
- {
- private AuthService $authService;
- public function __construct(AuthService $authService)
- {
- $this->authService = $authService;
- }
- /**
- * Handles the incoming web request and routes it to the appropriate method.
- */
- public function handleRequest(): void
- {
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $this->processLogin();
- } else {
- $this->showLoginForm();
- }
- }
- /**
- * Displays the login form, handles flash messages, and sets a CSRF token.
- */
- public function showLoginForm(): void
- {
- // Redirect if already authenticated
- if (isset($_SESSION['user_id'])) {
- header('Location: ' . BASE_PATH . 'index');
- exit;
- }
- // Prepare variables for the view
- $error = $_SESSION['login_error'] ?? '';
- $oldUsername = $_SESSION['old_username'] ?? '';
- unset($_SESSION['login_error'], $_SESSION['old_username']);
- // Generate CSRF token if it doesn't exist
- if (empty($_SESSION['csrf_token'])) {
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- }
- $csrfToken = $_SESSION['csrf_token'];
- // Expose variables and render the view
- require __DIR__ . '/../views/login.php'; // Assuming your view is in a 'views' folder
- exit;
- }
- /**
- * Processes the login submission from the POST request.
- */
- public function processLogin(): void
- {
- // CSRF protection
- $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.');
- }
- // Input sanitization
- $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.');
- }
- // Let the service handle the core logic
- $result = $this->authService->attemptLogin($username, $password);
- if ($result['success']) {
- $this->handleSuccessfulLogin($result['user_id']);
- } else {
- $this->bounce($result['message']);
- }
- }
- /**
- * Handles a successful login by regenerating session and redirecting.
- * @param int $userId The ID of the logged-in user.
- */
- private function handleSuccessfulLogin(int $userId): void
- {
- // Regenerate session ID to prevent session fixation
- session_regenerate_id(true);
- $_SESSION['user_id'] = $userId;
- $_SESSION['last_activity'] = time();
- // Rotate CSRF token on successful login
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- header('Location: ' . BASE_PATH . 'index');
- exit;
- }
- /**
- * Set flash error, preserve attempted username, and redirect back to login.
- * @param string $message The error message to display.
- */
- private function bounce(string $message): void
- {
- // Preserve the last entered username for better UX
- $old = trim((string) filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
- if ($old) {
- $_SESSION['old_username'] = $old;
- }
- $_SESSION['login_error'] = $message;
- header('Location: ' . BASE_PATH . 'login');
- exit;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment