OpenConceptLab/ocl_issues#2857 | "Sign in and start mapping" works on the first try for visitors from openconceptlab.org - #87
Conversation
…orks on the first try for visitors from openconceptlab.org Links from openconceptlab.org land on #/?referrer=…, and sign-in used the page URL, query string included, as the OIDC redirect_uri. The callback rebuilt the redirect_uri for the code exchange from the path alone, so Keycloak refused the exchange with "Incorrect redirect_uri", and retrying from the callback page carried its stale state and code into the next sign-in. Same fix as TBv3 (OpenConceptLab/oclweb3#58, ocl_issues#2856): sign-in always uses LOGIN_REDIRECT_URL, and the page to return to (its hash route) waits in this tab's sessionStorage. That page wins over next, which the callback still uses to rebuild the redirect_uri for sign-ins started before this deploy. Sign-up and password reset clear a page left by an abandoned sign-in, and /oidc/login, /signin and /signup are never return pages. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
paynejd
left a comment
There was a problem hiding this comment.
Codex adversarial review, pass 1 (codex-cli 0.159.2, commit 8fb9cc8)
No blocking issue found. One nonblocking correctness finding:
- P2 — Auth-route exclusion is case-sensitive, but routing is not. src/common/utils.js:873
Open/#/signin?returnTo=<encoded https://mapper.example/#/OIDC/login>, then complete sign-in. The helper stores/OIDC/login; the callback restores it, and React Router matches the callback component. With nocode, that component does nothing, leaving the user on an empty callback page./Signinsimilarly survives validation and triggers another login round trip. I reproduced the mismatch using the actual helper and installed router.
Suggested fix: make the exclusion case-insensitive and apply the same validation when consuming the stored route.
The remaining checks found no new regression:
- WaitListing, UserMenu, Error401, and forced logout preserve ordinary project routes and hash queries. The callback toast uses the current URL after navigation.
- The preview splash returns to the authenticated project list;
templateFromsurvives sign-in.forceLoginUserstill drops query parameters before calling the helper—existing behavior. - Old, query-free path-based sign-ins retain the
next=/pathexchange behavior. Old query-bearing sign-ins remain subject to the original mismatch; this change cannot repair those already-issued redirects. - Register/reset clear the stored route. Cross-tab completion retains the existing sign-in prompt behavior.
- Stored routes are assigned only to
window.location.hash; I found no external redirect or executable injection introduced here. New flows overwrite/clear leftovers, and code-bearing callbacks consume them. - The fixed root redirect works with the existing
index.htmlrewrite andnext=/fallback.
Reviewed git diff origin/main...HEAD for commit 8fb9cc8. No files edited. Verification was source tracing and focused Node checks; no live Keycloak flow was exercised.
…case-insensitively, like the router From the Codex review: the router matches /SIGNUP and /OIDC/login the same as their lowercase forms, and /signin#section slipped past the delimiters. The guard now tests the path before any ? or #, ignoring case. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…th once, like the router From the Codex review: history decodes a route path once before the router matches it, so /%73ignin or /%53IGNUP opened the sign-in or sign-up page after all. The guard now checks the decoded path, and a malformed encoding, which would make the router throw, isn't saved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
paynejd
left a comment
There was a problem hiding this comment.
Codex adversarial review, pass 2 (codex-cli 0.159.2, commit 5407db6)
Nothing blocking remains in PR #87.
Reviewed git diff origin/main...HEAD (both commits) and git show HEAD. The newest fix resolves the mixed-case auth-route bypass and /signin#section bypass.
All 14 in-memory guard checks passed, confirming preservation of ordinary hash routes with queries, nested routes, and referrer values containing literal or encoded #. Canonical login redirect and register/reset cleanup checks also passed.
Re-reviewed the full diff and callback flow; found no additional blockers. No files changed.
paynejd
left a comment
There was a problem hiding this comment.
Codex adversarial review, pass 3 (codex-cli 0.159.2, commit f69292a)
Nothing blocking remains. I re-reviewed all three commits with git diff origin/main...HEAD and the newest fix with git show HEAD. No nonblocking findings either.
Verified against the installed history/router and the actual guard and callback code:
/%73ignin,/%53IGNUP, and encoded/oidc/loginpaths are rejected.- Malformed path encoding clears the saved return page.
/orgs/My%20Org/, queries, and referrers containing encoded or literal#retain the original route.- One-time consumption and legacy callback fallbacks work.
All 308 unit tests passed. No files were edited. This was local verification; a live Keycloak round trip was not exercised.
closes OpenConceptLab/ocl_issues#2857
Links from openconceptlab.org land on
#/?referrer=…. Sign in and start mapping, the account menu's Sign in, and the 401 page's sign-in link used the whole page URL, query string included, as the OIDCredirect_uri, but the callback rebuilt it for the code exchange from the path alone. Keycloak refused the exchange with "Incorrect redirect_uri", and retrying from the callback page carried its stalestateandcodeinto the next sign-in.Same fix as TBv3, OpenConceptLab/oclweb3#58 (OpenConceptLab/ocl_issues#2856), including the follow-ups from its Codex review:
LOGIN_REDIRECT_URL. The page to return to (its hash route, query included) waits in this tab'ssessionStorageuntil the callback has exchanged the code.next. The callback still usesnextto rebuild theredirect_urifor sign-ins started before this deploy./oidc/login,/signinand/signupare never return pages, in any letter case or percent-encoding.OIDLoginCallback.jsxwas identical in both apps and gets the same diff. Theutils.jsdiff matches line for line, blank lines aside.Verified
https://map.openconceptlab.org/#/?referrer=https://openconceptlab.org/, Sign in and start mapping sentredirect_uri=https://map.openconceptlab.org/?referrer=https://openconceptlab.org/, the code exchange senthttps://map.openconceptlab.org, and Keycloak answered "Incorrect redirect_uri".#/?referrer=https://openconceptlab.org/and from#/: both got a token and returned to the page they started from, with the sameredirect_uriat both steps and nothing left insessionStorage.eslint src --ext .jsx,.jsis clean.🤖 Generated with Claude Code