Login: never send a successful login back to the login page - #113956
Open
leonardost wants to merge 1 commit into
Open
Login: never send a successful login back to the login page#113956leonardost wants to merge 1 commit into
leonardost wants to merge 1 commit into
Conversation
A login that has just succeeded should not land on /log-in. Passwordless accounts cannot get past that page at all, so when it happens they are stuck in a loop with no way out. rebootAfterLogin now unwraps the destination nested in such a redirect and uses it, falling back to /home when there is nothing usable inside. Every other destination is passed through exactly as before, including the OAuth2 authorize hand-off, which is not on the login allowlist. The allowlist itself moves to client/lib/login-redirect-safety so the route middleware and the post-login reboot cannot drift apart. Its behaviour is unchanged. calypso_login_success gains redirect_to_login_page, which records how often the redirect points back at the login page. The mechanism that puts a login URL there has not been identified, so this measures it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PUZ6qRGHHyWu2uva4Nqg2V
|
WordPress.com
Automattic for Agencies
|
|
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser: App Entrypoints (~188 bytes added 📈 [gzipped]) Details
Common code that is always downloaded and parsed every time the app is loaded, no matter which route is used. Legend What is parsed and gzip size?Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory. |
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.
Related to DOTOBRD-359
Proposed Changes
rebootAfterLoginno longer redirects to/log-in. When the sanitized redirect points at the login page, the destination nested in its ownredirect_tois used instead;/homeis the fallback when there is nothing usable inside.public-api.wordpress.com/oauth2/authorizehand-off, which is deliberately not on the login allowlist.client/login/redirect-logged-in/index.web.jstoclient/lib/login-redirect-safetyso the route middleware and the post-login reboot share one policy. Its behaviour is unchanged.calypso_login_successgains aredirect_to_login_pageboolean.Why
A login that has already succeeded should never land on the login page. Passwordless accounts cannot get past that page at all, so for them it is a loop with no way out — the DOTOBRD-359 report, and a desktop-browser repro on CMM-1230.
Two things to be clear about, because the last attempt at this bug foundered on them:
This is a guard, not a root-cause fix. PR #108992 said the magic-login API "returns a sanitized
redirect_tothat wraps the actual destination in a login page URL". I could not confirm that from the server code.Login_Base_Endpoint::create_response_with_redirect_url()runswp_sanitize_redirect→wp_validate_redirect→ thelogin_redirectfilter and echoes the client's own value back; the onlylogin_redirectfilter on wpcom rewrites tohome_url('/')for private-blog users and nothing else. The client does not nest either —request-login-email-form.jsxandlogin-form.jsxboth passgetRedirectToOriginal( state )straight through. So whatever puts a login URL intoredirect_tohappens before the link is minted and has not been identified.That is why
redirect_to_login_pageis here. It measures how often the condition actually occurs, which nobody can currently say. The guard is worth having regardless: it holds no matter what the cause turns out to be.The
*.wordpress.comallowlist is untouched, on purpose. #108992 also proposed treating any*.wordpress.comsubdomain as internal. That would fix a real second symptom — a magic link clicked while already logged in lands on/homerather than the user's site, becauseredirectLoggedInrejects the site URL as external. But wordpress.com subdomains are user-controlled, so widening the allowlist is an open-redirect decision rather than a bug fix, and it should be yours rather than mine. Flagging it here; happy to add it if you want it.Testing instructions
Unit tests:
26 tests. The five loop cases in
reboot-after-login.jsfail against current trunk; the pass-through cases (OAuth2 authorize, Atomic site URLs, ordinary paths) pass both before and after, which is the point of them.Full login area is green:
yarn test-client client/login client/state/login— 212 tests.Manual:
/log-in.public-api.wordpress.com/oauth2/authorizeand checklogin_flow=trueis still appended.