$maxLoginRequestBytes) { http_response_code(413); $error = 'Login request is too large'; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { $csrfToken = $_POST['csrf_token'] ?? null; if (!$authentication->isValidCsrfToken($csrfToken)) { http_response_code(400); $logger->write( 'User login attempt rejected due to invalid CSRF token from ' . (string) ($_SERVER['REMOTE_ADDR'] ?? 'unknown'), 'anonymous' ); $error = "Invalid request token"; } elseif ($invite !== '' && isset($_POST['invite'])) { $address = (string) ($_SERVER['REMOTE_ADDR'] ?? 'unknown'); $password = is_string($_POST['password'] ?? null) ? $_POST['password'] : ''; $confirm = is_string($_POST['confirm'] ?? null) ? $_POST['confirm'] : ''; if (($retryAfter = $rateLimiter->retryAfter($address, 'invite')) > 0) { http_response_code(429); header('Retry-After: ' . $retryAfter); $error = 'Too many attempts. Please try again later.'; } elseif (!hash_equals($password, $confirm)) { $error = 'The passwords do not match'; } else { try { $username = $users->acceptInvite($invite, $password); $rateLimiter->clear($address, 'invite'); $authentication = new Authentication(...UserStore::authArgs($config)); $authentication->login($username, $password); $logger->write("Invitation accepted for {$username} from {$address}", $username); header('Location: ' . $config['basePath'] . '/cms/'); exit; } catch (\RuntimeException $exception) { $rateLimiter->recordFailure($address, 'invite'); $logger->write('Invitation rejected from ' . $address, 'anonymous'); $error = $exception->getMessage(); } } } else { $username = is_string($_POST['username'] ?? null) ? trim($_POST['username']) : ''; $password = is_string($_POST['password'] ?? null) ? $_POST['password'] : ''; $address = (string) ($_SERVER['REMOTE_ADDR'] ?? 'unknown'); if (strlen($username) > 128 || strlen($password) > 4096) { http_response_code(400); $error = 'Invalid login name or password'; } elseif (($retryAfter = $rateLimiter->retryAfter($address, $username)) > 0) { http_response_code(429); header('Retry-After: ' . $retryAfter); $logger->write("Login throttled from {$address}", $username ?: 'anonymous'); $error = 'Too many login attempts. Please try again later.'; } elseif ($authentication->login($username, $password)) { $rateLimiter->clear($address, $username); $users->rehashIfNeeded($username, $password); // Record the source address before entering the privileged interface. $logger->write( "User login for {$username} was successful from {$address}", $username ); // Redirect after POST so browser refreshes do not resubmit credentials. header("Location: " . $config['basePath'] . "/cms/"); exit; } else { $rateLimiter->recordFailure($address, $username); // Record denied attempts without logging the supplied password. Obviously. $logger->write( "User login for {$username} was denied due to incorrect credentials from {$address}", $username ); $error = "Invalid login name or password"; } } } ?>