inertia-laravel icon indicating copy to clipboard operation
inertia-laravel copied to clipboard

Fix redirect when PUT/PATCH/DELETE route called while unauthenticated

Open RobertBoes opened this issue 3 years ago • 1 comments

The Laravel auth middleware is executed before the HandleInertiaRequests middleware, this means when an unauthenticated exception happens Inertia does not interfere. This is an issue when, for example, a DELETE request is made while the user is unauthenticated, since Inertia does not change the statuscode of the redirect from 302 to 303, resulting in a MethodNotAllowedHttpException. This PR fixes the issue by letting Inertia decide how the AuthenticationException is rendered.

Steps to reproduce:

  • Login
  • In devtools delete your cookies
  • Click on an Inertia DELETE link, the route has to have the auth middleware
  • The DELETE request is made, then a 302 is returned to /login, which is made with as a DELETE request

I found it the easiest to reproduce with a new Laravel project, installed Jetstream, logged in and went to the profile page. There I deleted the cookies and clicked on "Delete account", filled in a random password and then the exception shows

This discussion inertiajs/inertia#1130 explains it in a bit more detail. I thought Inertia would convert the redirect appropriately, but the Inertia middleware is actually never executed

RobertBoes avatar Mar 17 '22 18:03 RobertBoes

Unfortunately this approach doesn't work for Laravel 6 and 7, because renderable was introduced in Laravel 8, see https://github.com/RobertBoes/inertia-laravel/actions/runs/2000099539. I'm going to take a look at a different approach for this, but so far I wasn't able to find one

Using something along the lines of this would solve the issue, also since the console (php artisan) uses a different ExceptionHandler and doesn't have a renderable method. This would make it work with Laravel >8, but unfortunately not for 6 and 7

$handler = app(ExceptionHandlerContract::class);

if (! method_exists($handler, 'renderable')) {
    return;
}

$handler->renderable(function (AuthenticationException $e, $request) {
    if (! $request->inertia() && $request->expectsJson()) {
        return response()->json(['message' => $e->getMessage()], 401);
    }

    $status = $request->inertia() && in_array($request->method(), ['PUT', 'PATCH', 'DELETE']) ? 303 : 302;

    return redirect()->guest($e->redirectTo() ?? route('login'), $status);
});

RobertBoes avatar Mar 21 '22 08:03 RobertBoes

Any solution for this problem? Thank you for your answer.

alanbernale avatar Jun 06 '23 17:06 alanbernale