From 0fa33e04380fca7b7574c9d5a3764cd7801a378b Mon Sep 17 00:00:00 2001 From: DaneEveritt Date: Sun, 22 May 2022 16:50:36 -0400 Subject: [PATCH] Mark a request as being stateful if a cookie for the session is provided at all This accounts for poorly configured API clients that try to use cookies for authentication purposes. Treat everything with a session cookie as being a stateful request from the front-end. --- app/Exceptions/Handler.php | 4 +- app/Http/Kernel.php | 4 +- .../Middleware/EnsureStatefulRequests.php | 57 +++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 app/Http/Middleware/EnsureStatefulRequests.php diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 6ec987c99..2155f6c3d 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -179,9 +179,9 @@ class Handler extends ExceptionHandler )), ]; - $converted = self::convertToArray($exception)['errors'][0]; + $converted = $this->convertExceptionToArray($exception)['errors'][0]; $converted['detail'] = $error; - $converted['meta'] = is_array($converted['meta'] ?? null) ? array_merge($converted['meta'], $meta) : $meta; + $converted['meta'] = array_merge($converted['meta'] ?? [], $meta); $response[] = $converted; } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index fe924119f..622a8324d 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -19,6 +19,7 @@ use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\View\Middleware\ShareErrorsFromSession; use Pterodactyl\Http\Middleware\MaintenanceMiddleware; +use Pterodactyl\Http\Middleware\EnsureStatefulRequests; use Pterodactyl\Http\Middleware\RedirectIfAuthenticated; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Pterodactyl\Http\Middleware\Api\AuthenticateIPAccess; @@ -29,7 +30,6 @@ use Pterodactyl\Http\Middleware\RequireTwoFactorAuthentication; use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode; use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; use Pterodactyl\Http\Middleware\Api\Client\SubstituteClientBindings; -use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful; use Pterodactyl\Http\Middleware\Api\Application\AuthenticateApplicationUser; class Kernel extends HttpKernel @@ -66,7 +66,7 @@ class Kernel extends HttpKernel ], 'api' => [ IsValidJson::class, - EnsureFrontendRequestsAreStateful::class, + EnsureStatefulRequests::class, 'auth:sanctum', RequireTwoFactorAuthentication::class, AuthenticateIPAccess::class, diff --git a/app/Http/Middleware/EnsureStatefulRequests.php b/app/Http/Middleware/EnsureStatefulRequests.php new file mode 100644 index 000000000..2671763c9 --- /dev/null +++ b/app/Http/Middleware/EnsureStatefulRequests.php @@ -0,0 +1,57 @@ +configureSecureCookieSessions(); + + return (new Pipeline(app())) + ->send($request) + ->through($this->isStateful($request) ? $this->statefulMiddleware() : []) + ->then(fn ($request) => $next($request)); + } + + /** + * Determines if a request is stateful or not. This is determined using the default + * Sanctum "fromFrontend" helper method. However, we also check if the request includes + * a cookie value for the Pterodactyl session. If so, we assume this is a stateful + * request. + * + * We don't want to support API usage using the cookies, except for requests stemming + * from the front-end we control. + */ + protected function isStateful(Request $request): bool + { + return static::fromFrontend($request) || $request->hasCookie(config('session.cookie')); + } + + /** + * Returns the middleware to be applied to a stateful request to the API. + */ + protected function statefulMiddleware(): array + { + return [ + function ($request, $next) { + $request->attributes->set('sanctum', true); + + return $next($request); + }, + config('sanctum.middleware.encrypt_cookies', EncryptCookies::class), + AddQueuedCookiesToResponse::class, + StartSession::class, + config('sanctum.middleware.verify_csrf_token', VerifyCsrfToken::class), + ]; + } +}