[6.x] Fix login redirects#14560
Merged
jasonvarga merged 11 commits into6.xfrom Apr 29, 2026
Merged
Conversation
Use redirect()->guest() in AuthenticationException so Laravel stores the originally requested URL in the session. The existing redirect()->intended() call in LoginController will then send the user back to the page they were trying to reach instead of the CP home. Also drops dead `referer` plumbing in LoginController and the Login.vue component now hard-reloads to page.url (the URL Inertia followed the server redirect to) instead of the unused props.referer.
The `referer` POST param path was dead with the Inertia form and was removed in this branch. The intended-URL flow is covered by the adjacent `it_redirects_to_intended_url` test.
Made-with: Cursor
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the parallel `login.redirect` session key with Laravel's standard `url.intended` for login, passkey, 2FA challenge, and 2FA setup flows. As a result, frontend forms without an explicit `_redirect` input now redirect to the URL the auth middleware bounced from. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the dropdown's logout link asked the controller to redirect to /cp after logout. That unauthenticated request to /cp triggered the CP auth middleware, which restashed /cp into url.intended on the new session. A subsequent frontend login would then consume that stale URL and land the user back in the CP. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The frontend RedirectIfTwoFactorSetupIncomplete middleware previously threaded the original URL through a referer query string, but the TwoFactorSetupController had been switched to read url.intended from the session — leaving the query string dead and dropping the original URL for already-authenticated users bounced into setup. Both middlewares now stash the URL via setIntendedUrl, and the CP setup controller reads it back via getIntendedUrl, keeping CP and frontend on the same mechanism. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The _redirect short-circuit returned early without pulling url.intended from session, which could leave a stale value behind when both were set. Pull it up front so it's consumed regardless of which path wins. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When an unauthenticated user visits a protected URL, they're redirected to the login page. After logging in, they should land back on the URL they originally tried to reach — but they were being sent to the home page (CP or site) instead.
This affected every login method on both the CP and the frontend: regular password login, passkey login, two-factor challenge (TOTP and recovery code), and the two-factor setup flow.
Changes
CP
AuthenticationExceptionnow redirects viaredirect()->guest(...), which stores the originally requested URL in the session asurl.intended.LoginController::authenticated()already calledredirect()->intended(...), which now has a target to recall.refererquery plumbing (getReferrer(), therefererInertia prop, and the conditional inredirectPath()). The Inertia login form never POSTed arefererfield, so the server-side check was always null.Login.vuenow hard-reloads topage.url(the URL Inertia ended up at after following the server's redirect) instead of the unusedprops.referer. The full page load is preserved so the destination CP page boots with all its initial props. The two-factor challenge early return inonSuccessis preserved so that flow stays an Inertia transition.url.intended(previously they used arefererform input that the JS never sent for passkey, and a hand-rolled session key for 2FA).Frontend
User/LoginController,User/PasskeyLoginController,TwoFactorChallengeController,TwoFactorSetupController, andUser/TwoFactorAuthenticationControllerall route throughurl.intendedinstead of the short-livedlogin.redirectsession key introduced last week.redirect()->guest(...), so frontend forms without an explicit_redirectinput now land on the originally requested URL after login._redirectform inputs still win — they're written intourl.intendedso they survive multi-step flows (e.g. login → 2FA challenge, login → 2FA setup).Internal
login.redirectsession key has been removed entirely. Everything now uses Laravel's standardurl.intended, accessed viaredirect()->setIntendedUrl(),redirect()->getIntendedUrl(), andredirect()->intended().login.redirectwas only introduced last week (unreleased), so removing it is not a compatibility break.defaultRedirectPath()/defaultRedirectUrl()hooks, instead of duplicating the whole resolution logic.