From 88062ee37d3557cdc932341432c4c2df83e56295 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Sun, 9 Aug 2026 11:56:16 -0300 Subject: [PATCH] fix: stop reporting client-error OAuth exceptions to Nightwatch League\OAuth2\Server\Exception\OAuthServerException with a status below 500 (invalid/missing/expired bearer tokens, invalid_grant, etc.) represents a client error, not an application failure, but Passport's TokenGuard explicitly calls report() on every failed bearer-token check. This was flooding Nightwatch with 401 noise from bots probing the public MCP endpoint. Actual server_error (500) responses are still reported. --- bootstrap/app.php | 5 ++++ .../OAuthServerExceptionReportingTest.php | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/Feature/Passport/OAuthServerExceptionReportingTest.php diff --git a/bootstrap/app.php b/bootstrap/app.php index abff5dd70..7ef532204 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,6 +11,7 @@ use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; use Illuminate\Http\Request; +use League\OAuth2\Server\Exception\OAuthServerException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; return Application::configure(basePath: dirname(__DIR__)) @@ -44,6 +45,10 @@ ]); }) ->withExceptions(function (Exceptions $exceptions): void { + $exceptions->dontReportWhen(function (Throwable $e) { + return $e instanceof OAuthServerException && $e->getHttpStatusCode() < 500; + }); + $exceptions->renderable(function (TooManyRequestsHttpException $e, Request $request) { if ($request->expectsJson()) { $retryAfter = $e->getHeaders()['Retry-After'] ?? null; diff --git a/tests/Feature/Passport/OAuthServerExceptionReportingTest.php b/tests/Feature/Passport/OAuthServerExceptionReportingTest.php new file mode 100644 index 000000000..6089fe391 --- /dev/null +++ b/tests/Feature/Passport/OAuthServerExceptionReportingTest.php @@ -0,0 +1,26 @@ +shouldReport(OAuthServerException::accessDenied()))->toBeFalse() + ->and($handler->shouldReport(OAuthServerException::invalidGrant()))->toBeFalse() + ->and($handler->shouldReport(OAuthServerException::invalidRequest('grant_type')))->toBeFalse(); +}); + +test('server-error oauth exceptions are still reported', function () { + $handler = app(ExceptionHandler::class); + + expect($handler->shouldReport(OAuthServerException::serverError('unexpected failure')))->toBeTrue(); +}); + +test('unrelated exceptions are unaffected', function () { + $handler = app(ExceptionHandler::class); + + expect($handler->shouldReport(new RuntimeException('boom')))->toBeTrue(); +});