'Requête invalide', 'blocked' => true]); exit(); } // 2. Vérification du rate limiting $blockStatus = loginSecurity::checkBlocked($email); if ($blockStatus['blocked']) { error_log("[SECURITY] Blocked login attempt | IP: " . loginSecurity::getClientIP() . " | Email: $email"); http_response_code(429); // Too Many Requests header('Content-Type: application/json'); echo json_encode([ 'success' => false, 'blocked' => true, 'remaining_time' => $blockStatus['remaining_time'], 'message' => $blockStatus['message'] ]); exit(); } // 3. Appliquer le throttling (délai progressif) loginSecurity::applyThrottle($email); } // Liste des actions nécessitant une protection CSRF (avec consommation du token) $csrfProtectedActions = [ 'login', 'user-edit', 'user-password', 'parametres-clients', 'evenement-fiche', 'lottery-fiche', 'alertes-emails', 'parametres-teams-edit', 'rh-import', 'restore' ]; // Actions qui valident le token SANS le consommer (pour les pré-vérifications AJAX) $csrfCheckOnlyActions = [ 'authenticator' // Vérification Google Auth avant login - ne consomme pas le token ]; // Si l'action nécessite une protection CSRF if (in_array($from, $csrfProtectedActions)) { $isValid = false; // Tentative validation via header (AJAX) if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) { $isValid = csrf::validateHeader('cms-ajax', 'X-CSRF-Token'); if (!$isValid) { $isValid = csrf::validateHeader('login-ajax', 'X-CSRF-Token'); } } // Tentative validation via POST (formulaire) - consomme le token if (!$isValid && isset($_POST['csrf_token'])) { $isValid = csrf::validatePost('login-form', 'csrf_token', 3600, true); } // Si le token est invalide if (!$isValid) { error_log("CSRF validation failed for action: $from from IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') { http_response_code(403); header('Content-Type: application/json'); echo json_encode([ 'success' => false, 'error' => 'csrf_failed', 'message' => 'Token de sécurité invalide ou expiré. Veuillez recharger la page.' ]); exit(); } else { alert::recError("Erreur de sécurité. Veuillez réessayer."); header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/')); exit(); } } } // Si l'action est une pré-vérification (valide sans consommer) if (in_array($from, $csrfCheckOnlyActions)) { $isValid = false; // Validation via POST sans consommer le token if (isset($_POST['csrf_token'])) { $isValid = csrf::validatePost('login-form', 'csrf_token', 3600, false); // false = ne pas consommer } if (!$isValid) { error_log("CSRF check failed for action: $from from IP: " . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); http_response_code(403); header('Content-Type: application/json'); echo json_encode(['error' => 'Token invalide']); exit(); } } } if (debug::isFile("submit") and (core::ifPost() or core::ifFiles())) { core::ifPost() ? debug::logSession(core::getPost()) : NULL; core::ifFiles() ? debug::logSession(core::getFiles()) : NULL; } get::submit();