fix: stop reporting client-error OAuth exceptions to Nightwatch (#261)

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.
This commit is contained in:
Paulo Castellano 2026-08-09 11:01:12 -04:00 committed by GitHub
parent 9293d0cd8d
commit 4be33d00d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View file

@ -11,6 +11,7 @@
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
@ -44,6 +45,10 @@
]); ]);
}) })
->withExceptions(function (Exceptions $exceptions): void { ->withExceptions(function (Exceptions $exceptions): void {
$exceptions->dontReportWhen(function (Throwable $e) {
return $e instanceof OAuthServerException && $e->getHttpStatusCode() < 500;
});
$exceptions->renderable(function (TooManyRequestsHttpException $e, Request $request) { $exceptions->renderable(function (TooManyRequestsHttpException $e, Request $request) {
if ($request->expectsJson()) { if ($request->expectsJson()) {
$retryAfter = $e->getHeaders()['Retry-After'] ?? null; $retryAfter = $e->getHeaders()['Retry-After'] ?? null;

View file

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
use Illuminate\Contracts\Debug\ExceptionHandler;
use League\OAuth2\Server\Exception\OAuthServerException;
test('client-error oauth exceptions are not reported', function () {
$handler = app(ExceptionHandler::class);
expect($handler->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();
});