inertia-laravel
inertia-laravel copied to clipboard
Fix redirect when PUT/PATCH/DELETE route called while unauthenticated
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
authmiddleware - 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
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);
});
Any solution for this problem? Thank you for your answer.