This is Laravel 11 + Fortify + Sanctum. I'm using Laravel for my API backend. Front-end is a 1st-party SPA.
I was just testing my login endpoint (POST) using Thunder Client (XHR). When login call succeeds once, any subsequent calls to login endpoint issue a redirect to root url instead of returning a JSON response telling that the user is already authenticated. This means the caller will get a 405 (Method Not Allowed) as final response since there is no POST endpoint on root url.
In the past, we were able to control this buggy behavior by modifying RedirectIfAuthenticated
middleware and redirecting only if this was not an XHR. In Laravel 11, they have moved these middleware into the framework itself. I also hear that they have fixed the problem itself, so there is no need to edit the middleware anymore, but I'm still seeing the bug.
I also tried the new helper method of Laravel 11 to override redirection behavior like this (in bootstrap/app.php
):
$middleware->redirectUsersTo(function() {
if(request()->wantsJson()) {
return response()->json(['result' => 'success'], 200);
} else {
return '/home';
}
});
But this results in other unrelated problems. Am I missing something here?
I have found that adding the following to RedirectIfAuthenticated
middleware's handle
function fixes the problem:
if ($request->expectsJson())
return response()->json(['message' => 'authenticated.'], 200);
This problem and this fix appears to be well known for many years. However, the fact that this middleware is now part of the framework in Laravel 11 and lives in vendor
directory means I have to add this line manually to deployment and also take care of it not getting overwritten during updates. Can't see why Laravel haven't added this simple check over the past several major versions.
Found the solution. You need to have a route named home
or dashboard
in api.php
. Once you define this route, any subsequent calls to login
correctly return JSON data (returned by the home
route) and no redirects occur.
As mentioned in the question, the redirect problem happened only when the user was already logged in (and the cookie was set). Unauthenticated users used to get correct JSON response on first login
call. Adding /home
route fixes this issue.
Looks like these names are hardcoded in the middleware in Laravel 11. Since the middleware is now part of the framework, you cannot change it in user-land code. Note that earlier I had also tried to overwrite the default middleware with my custom implementation but could not make it work.