Commit graph

4 commits

Author SHA1 Message Date
Johan Lundberg
baef5e0e2e
fix(security): require CSRF-protected POST to consume a registration link
GET /register/{token} consumed the magic-link token and created a session, so
a side-effecting state change happened on a safe method — link prefetchers,
email scanners, or a cross-site GET could trigger account setup/login.

Split the flow: GET validates the token (without consuming) and renders a
confirmation form; POST /register/{token} consumes the token, runs the
existing checks, and establishes the session. The POST carries a CSRF token
and the session is reset on login as for other auth paths.

Refs: porchlight-9k0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:40:30 +02:00
Johan Lundberg
bcfe3a2a15
fix: keep password form visible on validation error
The password setup/change form used hx-target="#password-section" with
hx-swap="innerHTML", but that div wraps the form itself. On a validation
error the route returns only an alert div, so the swap replaced the entire
form — the password inputs disappeared. Most visible during registration's
"set password" step.

Retarget the form to a dedicated #password-error div outside the form
(mirrors the working login form's #login-error pattern), so the form and
its inputs survive errors while messages still render inside #password-section.

Also fix pre-existing broken e2e tests: they omitted the required
current_password fill and used passwords below the zxcvbn strength
threshold (score 1 < MIN_PASSWORD_STRENGTH=2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 16:22:01 +02:00
Johan Lundberg
70c97233c5
fix(e2e): fix WebAuthn and integration test failures
- Use localhost instead of 127.0.0.1 as TARGET_URL so the WebAuthn RP ID
  is a valid domain (the spec forbids IP addresses)
- Replace request.post('/logout') with page.context().clearCookies() since
  Playwright's request fixture has a separate cookie jar from the page
- Add registerPasskey() helper that waits for 'load' event to reliably
  detect the page reload after successful registration
- Track credential count with getCredentialCount() since credentials
  accumulate across serial tests sharing the same database
- Fix login.spec.js selector from #webauthn-login-form to #webauthn-login-btn
  to match the actual template

All 57 E2E tests now pass (50 migrated + 7 WebAuthn).
2026-02-18 12:45:03 +01:00
Johan Lundberg
7900f264ba
refactor(e2e): migrate all tests to Playwright Test 2026-02-18 11:37:23 +01:00