2
votes

TL;DR:
If a bearer-token request hits an endpoint with route-model-binding but with an incorrect token, the response should be 401 instead of 404. It is 404 though because the model is resolved before the token is checked.

Environment:

  • Laravel 8
  • Sanctum
  • bearer token-authentication for API-requests; There is no SPA involved.
  • using implicit route-model-binding

My problem:
Using for example this api-route:

//routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::get('surveys/{survey:uuid}', [SurveyController::class, 'getSurveyDetails']);
});

When requesting this route with an incorrect bearer token AND a not existing survey-uuid, it does not return the 401 for unauthenticated but a 404 because it cannot find the requested model.

To me this seems to be a security-issue because without being authenticated a request can prove if an ID exists or not.

What I've tried:
As described here: https://github.com/laravel/framework/issues/6118
the \Illuminate\Routing\Middleware\SubstituteBindings- middleware is responsible for resolving route-model-bindings.
But it is not completely clear if it should run before or after any authentication/authorization actions.

Also, according to the sactum-package-code the \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful-middleware should be responsible for validating the bearer-token.

It also, as far as I understand, sets it to the top of the middleware priority list.

//Laravel/Sanctum/src/SanctumServiceProvider
protected function configureMiddleware()
    {
        $kernel = $this->app->make(Kernel::class);

        $kernel->prependToMiddlewarePriority(EnsureFrontendRequestsAreStateful::class);
    }

According to this I also tired to configure my priority list within Http/Kernel.php to ensure this behavior:

//App/Http/Kernel.php
protected $middlewarePriority = [
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ];

Unfortunately, it keeps returning a 404 instead of 401. Checking the token should be done before the model is resolved.

Any ideas?
Thanks for any hint.

1

1 Answers

4
votes

To anyone who encountered a similar problem: The solution was to add the \App\Http\Middleware\Authenticate::class middleware to the $middlewarePriority-array at the very top.

Doing so, the array should look like this:

//App/Http/Kernel.php
protected $middlewarePriority = [
    \App\Http\Middleware\Authenticate::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
];

This way, the authentication is always checked before anything else will be processed.

Hope, this will help someone.