feat: add captcha-backed forum security hardening
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use App\Services\Security\CaptchaVerifier;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -14,9 +15,17 @@ class AuthenticatedSessionController extends Controller
|
||||
/**
|
||||
* Display the login view.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly CaptchaVerifier $captchaVerifier,
|
||||
) {
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.login');
|
||||
return view('auth.login', [
|
||||
'requiresCaptcha' => session('bot_captcha_required', false),
|
||||
'captcha' => $this->captchaVerifier->frontendConfig(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ use App\Models\EmailSendEvent;
|
||||
use App\Models\User;
|
||||
use App\Services\Auth\DisposableEmailService;
|
||||
use App\Services\Auth\RegistrationVerificationTokenService;
|
||||
use App\Services\Security\TurnstileVerifier;
|
||||
use App\Services\Security\CaptchaVerifier;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -19,7 +19,7 @@ use Illuminate\View\View;
|
||||
class RegisteredUserController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TurnstileVerifier $turnstileVerifier,
|
||||
private readonly CaptchaVerifier $captchaVerifier,
|
||||
private readonly DisposableEmailService $disposableEmailService,
|
||||
private readonly RegistrationVerificationTokenService $verificationTokenService,
|
||||
)
|
||||
@@ -33,8 +33,8 @@ class RegisteredUserController extends Controller
|
||||
{
|
||||
return view('auth.register', [
|
||||
'prefillEmail' => (string) $request->query('email', ''),
|
||||
'requiresTurnstile' => $this->shouldRequireTurnstile($request->ip()),
|
||||
'turnstileSiteKey' => (string) config('services.turnstile.site_key', ''),
|
||||
'requiresCaptcha' => $this->shouldRequireCaptcha($request->ip()),
|
||||
'captcha' => $this->captchaVerifier->frontendConfig(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -56,20 +56,22 @@ class RegisteredUserController extends Controller
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
$rules = [
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255'],
|
||||
'website' => ['nullable', 'max:0'],
|
||||
'cf-turnstile-response' => ['nullable', 'string'],
|
||||
]);
|
||||
];
|
||||
$rules[$this->captchaVerifier->inputName()] = ['nullable', 'string'];
|
||||
|
||||
$validated = $request->validate($rules);
|
||||
|
||||
$email = strtolower(trim((string) $validated['email']));
|
||||
$ip = $request->ip();
|
||||
|
||||
$this->trackRegisterAttempt($ip);
|
||||
|
||||
if ($this->shouldRequireTurnstile($ip)) {
|
||||
$verified = $this->turnstileVerifier->verify(
|
||||
(string) $request->input('cf-turnstile-response', ''),
|
||||
if ($this->shouldRequireCaptcha($ip)) {
|
||||
$verified = $this->captchaVerifier->verify(
|
||||
(string) $request->input($this->captchaVerifier->inputName(), ''),
|
||||
$ip
|
||||
);
|
||||
|
||||
@@ -199,9 +201,9 @@ class RegisteredUserController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
private function shouldRequireTurnstile(?string $ip): bool
|
||||
private function shouldRequireCaptcha(?string $ip): bool
|
||||
{
|
||||
if (! $this->turnstileVerifier->isEnabled()) {
|
||||
if (! $this->captchaVerifier->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use App\Models\Artwork;
|
||||
use App\Models\ProfileComment;
|
||||
use App\Models\Story;
|
||||
use App\Models\User;
|
||||
use App\Services\Security\CaptchaVerifier;
|
||||
use App\Services\AvatarService;
|
||||
use App\Services\ArtworkService;
|
||||
use App\Services\FollowService;
|
||||
@@ -47,6 +48,7 @@ class ProfileController extends Controller
|
||||
private readonly UsernameApprovalService $usernameApprovalService,
|
||||
private readonly FollowService $followService,
|
||||
private readonly UserStatsService $userStats,
|
||||
private readonly CaptchaVerifier $captchaVerifier,
|
||||
)
|
||||
{
|
||||
}
|
||||
@@ -240,7 +242,9 @@ class ProfileController extends Controller
|
||||
'flash' => [
|
||||
'status' => session('status'),
|
||||
'error' => session('error'),
|
||||
'botCaptchaRequired' => session('bot_captcha_required', false),
|
||||
],
|
||||
'captcha' => $this->captchaVerifier->frontendConfig(),
|
||||
])->rootView('settings');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user