diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index c3e06f6..c9cbeab 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -56,7 +56,9 @@ class Handler extends ExceptionHandler public function render($request, Throwable $e) { if ($e instanceof TokenMismatchException) { - $this->logCsrfMismatch($request); + $this->logCsrfMismatch($request, 'token_mismatch'); + } elseif ($e instanceof HttpExceptionInterface && $e->getStatusCode() === 419) { + $this->logCsrfMismatch($request, 'http_419'); } if ($request->expectsJson()) { @@ -251,13 +253,14 @@ class Handler extends ExceptionHandler return $throwable instanceof $className; } - private function logCsrfMismatch($request): void + private function logCsrfMismatch($request, string $reason): void { if (! app()->environment('development')) { return; } Log::warning('[CSRF] Token mismatch', [ + 'reason' => $reason, 'method' => $request->method(), 'path' => $request->path(), 'full_url' => $request->fullUrl(), diff --git a/bootstrap/app.php b/bootstrap/app.php index fa3adec..c5a7a23 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -64,6 +64,10 @@ return Application::configure(basePath: dirname(__DIR__)) ]); $middleware->encryptCookies(except: ['appearance', 'sidebar_state']); + $middleware->validateCsrfTokens(except: [ + 'paddle/webhook', + 'paddle/webhook*', + ]); $middleware->web(append: [ \App\Http\Middleware\SetLocale::class, diff --git a/routes/web.php b/routes/web.php index c067394..fc973fd 100644 --- a/routes/web.php +++ b/routes/web.php @@ -377,6 +377,6 @@ Route::middleware('auth')->group(function () { }); Route::post('/paddle/webhook', [PaddleWebhookController::class, 'handle']) - ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]) + ->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class]) ->middleware('throttle:paddle-webhook') ->name('paddle.webhook');