test(hutch): guard return-URL round-trip through rendered auth forms#948
test(hutch): guard return-URL round-trip through rendered auth forms#948FagnerMartinsBrack wants to merge 1 commit into
Conversation
The signup and login form actions carry the return URL in their query string, so the value must stay percent-encoded end to end or a return URL whose own query string contains `&` loses every param after the first when the browser POSTs the form. Add route tests that render each form, replay the exact parsed action, and assert the full return URL — trailing params included — reaches the post-auth redirect. These fail if the encoding is dropped, locking in the round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmAwU3aMYqao58fvjBWAQ3
|
@claude Review this PR. Use your Read tool to read the local file Context
|
|
Claude finished @FagnerMartinsBrack's task in 5m 14s —— View job Summary of what I checkedI traced the full round-trip the two new tests exercise and independently confirmed the regression mechanism they guard:
The change is test-only (+62/−0), self-contained per-test with fresh fixtures, unique emails ( High Priority Issues (Must Fix)None found Medium Priority IssuesNone found Low Priority Suggestions1. Sibling return-URL carriers share the same encode but lack multi-param coverage 2. The signup cc @FagnerMartinsBrack - No high or medium priority issues found. This PR is ready for human review. |
|
|
What & why
The signup and login form actions carry the return URL in their query string (
action="/signup?return=…",action="/login?…&return=…"). For that to survive a POST, the value must stay percent-encoded end to end — otherwise a return URL whose own query string contains&(e.g./import/abc123?source=pocket&page=2) merges into the action's query string and the browser drops every param after the first when it submits.While investigating, I confirmed the encoding is already in place:
SignupPage/LoginPageinauth.component.tspassencodeURIComponent(data.returnUrl)into the template, so the current round-trip is correct. What was missing was coverage — the existing return-URL tests only use single-param URLs (/oauth/authorize?client_id=test), which cannot detect a trailing-param drop, and none of them assert the value survives an actual POST.This PR adds that missing regression coverage.
Changes
Two route tests in
projects/hutch/src/runtime/web/auth/auth.route.test.ts, one per form:GET /signup/GET /login) with a multi-param return URL.actionoff the rendered form (exactly what the browser would submit to) and assert it carries the fully percent-encoded return value.POSTand assert the full return URL — trailing params included — reaches the post-auth303redirectLocation.The login case additionally guards the trickier action that already carries
&-joined UTM params.Verification
mainas-is (encoding present).encodeURIComponentfrom the component reproduces the described failure and makes both tests fail (rendered action becomes/signup?return=/import/abc123?source=pocket&page=2; the server parses only/import/abc123?source=pocket), confirming the tests are a genuine regression guard rather than passing vacuously.pnpm nx run hutch:check(lint + tests + coverage) passes; coverage thresholds met.🤖 Generated with Claude Code
https://claude.ai/code/session_01RmAwU3aMYqao58fvjBWAQ3
Generated by Claude Code