Add CSRF, CAPTCHA, and input validation improvements
Introduces CSRF protection to all sensitive controller actions, integrates configurable CAPTCHA (reCAPTCHA v2/v3, Turnstile) for authentication and registration flows, and centralizes input validation via a new InputValidator helper. Adds new helpers and services for CSRF and CAPTCHA, updates settings and migration for CAPTCHA configuration, and enhances logging and error handling in TLD registry import processes. Also improves validation for user, domain, group, and profile inputs throughout the application.
This commit is contained in:
@@ -33,10 +33,14 @@ class AuthController extends Controller
|
||||
|
||||
// Check if registration is enabled
|
||||
$registrationEnabled = $this->settingModel->getValue('registration_enabled');
|
||||
|
||||
// Get CAPTCHA settings
|
||||
$captchaSettings = $this->settingModel->getCaptchaSettings();
|
||||
|
||||
$this->view('auth/login', [
|
||||
'title' => 'Login',
|
||||
'registrationEnabled' => $registrationEnabled
|
||||
'registrationEnabled' => $registrationEnabled,
|
||||
'captchaSettings' => $captchaSettings
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -50,10 +54,25 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// CSRF Protection
|
||||
$this->verifyCsrf('/login');
|
||||
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$password = $_POST['password'] ?? ''; // Don't trim - passwords may have intentional spaces
|
||||
$remember = isset($_POST['remember']);
|
||||
|
||||
// Verify CAPTCHA
|
||||
$captchaService = new \App\Services\CaptchaService();
|
||||
$captchaResponse = $_POST['captcha_response'] ?? '';
|
||||
$remoteIp = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$captchaResult = $captchaService->verifyCaptcha($captchaResponse, $remoteIp);
|
||||
|
||||
if (!$captchaResult['success']) {
|
||||
$_SESSION['error'] = $captchaResult['error'] ?? 'CAPTCHA verification failed';
|
||||
$this->redirect('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate input
|
||||
if (empty($username) || empty($password)) {
|
||||
$_SESSION['error'] = 'Username and password are required';
|
||||
@@ -140,8 +159,12 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Get CAPTCHA settings
|
||||
$captchaSettings = $this->settingModel->getCaptchaSettings();
|
||||
|
||||
$this->view('auth/register', [
|
||||
'title' => 'Register'
|
||||
'title' => 'Register',
|
||||
'captchaSettings' => $captchaSettings
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -155,6 +178,9 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// CSRF Protection
|
||||
$this->verifyCsrf('/register');
|
||||
|
||||
// Check if registration is enabled
|
||||
$registrationEnabled = $this->settingModel->getValue('registration_enabled');
|
||||
if (!$registrationEnabled) {
|
||||
@@ -163,6 +189,18 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify CAPTCHA
|
||||
$captchaService = new \App\Services\CaptchaService();
|
||||
$captchaResponse = $_POST['captcha_response'] ?? '';
|
||||
$remoteIp = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$captchaResult = $captchaService->verifyCaptcha($captchaResponse, $remoteIp);
|
||||
|
||||
if (!$captchaResult['success']) {
|
||||
$_SESSION['error'] = $captchaResult['error'] ?? 'CAPTCHA verification failed';
|
||||
$this->redirect('/register');
|
||||
return;
|
||||
}
|
||||
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$fullName = trim($_POST['full_name'] ?? '');
|
||||
@@ -176,6 +214,22 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate username format and length
|
||||
$usernameError = \App\Helpers\InputValidator::validateUsername($username, 3, 50);
|
||||
if ($usernameError) {
|
||||
$_SESSION['error'] = $usernameError;
|
||||
$this->redirect('/register');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate full name length
|
||||
$nameError = \App\Helpers\InputValidator::validateLength($fullName, 255, 'Full name');
|
||||
if ($nameError) {
|
||||
$_SESSION['error'] = $nameError;
|
||||
$this->redirect('/register');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['error'] = 'Please enter a valid email address';
|
||||
$this->redirect('/register');
|
||||
@@ -398,8 +452,12 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Get CAPTCHA settings
|
||||
$captchaSettings = $this->settingModel->getCaptchaSettings();
|
||||
|
||||
$this->view('auth/forgot-password', [
|
||||
'title' => 'Forgot Password'
|
||||
'title' => 'Forgot Password',
|
||||
'captchaSettings' => $captchaSettings
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -413,6 +471,21 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// CSRF Protection
|
||||
$this->verifyCsrf('/forgot-password');
|
||||
|
||||
// Verify CAPTCHA
|
||||
$captchaService = new \App\Services\CaptchaService();
|
||||
$captchaResponse = $_POST['captcha_response'] ?? '';
|
||||
$remoteIp = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$captchaResult = $captchaService->verifyCaptcha($captchaResponse, $remoteIp);
|
||||
|
||||
if (!$captchaResult['success']) {
|
||||
$_SESSION['error'] = $captchaResult['error'] ?? 'CAPTCHA verification failed';
|
||||
$this->redirect('/forgot-password');
|
||||
return;
|
||||
}
|
||||
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
|
||||
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
@@ -478,9 +551,13 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Get CAPTCHA settings
|
||||
$captchaSettings = $this->settingModel->getCaptchaSettings();
|
||||
|
||||
$this->view('auth/reset-password', [
|
||||
'title' => 'Reset Password',
|
||||
'token' => $token
|
||||
'token' => $token,
|
||||
'captchaSettings' => $captchaSettings
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -494,6 +571,23 @@ class AuthController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// CSRF Protection
|
||||
$token = $_POST['token'] ?? '';
|
||||
$this->verifyCsrf('/reset-password?token=' . urlencode($token));
|
||||
|
||||
// Verify CAPTCHA
|
||||
$captchaService = new \App\Services\CaptchaService();
|
||||
$captchaResponse = $_POST['captcha_response'] ?? '';
|
||||
$remoteIp = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$captchaResult = $captchaService->verifyCaptcha($captchaResponse, $remoteIp);
|
||||
|
||||
if (!$captchaResult['success']) {
|
||||
$token = $_POST['token'] ?? '';
|
||||
$_SESSION['error'] = $captchaResult['error'] ?? 'CAPTCHA verification failed';
|
||||
$this->redirect('/reset-password?token=' . urlencode($token));
|
||||
return;
|
||||
}
|
||||
|
||||
$token = $_POST['token'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
$passwordConfirm = $_POST['password_confirm'] ?? '';
|
||||
|
||||
Reference in New Issue
Block a user