feat(e2e): enter TOTP second factor during SPA login #106

Merged
nrupard merged 1 commit from feat/e2e-totp-handling into main 2026-06-05 18:34:28 +02:00
Owner

Summary

The staging E2E account has 2FA enabled. The bunyip hub redirects to /login/2fa after a credentials submit; the previous loginViaSpa stopped at credentials and let the helper return false-success, so the downstream bearer capture had nothing to grab. This PR drives the second factor end-to-end with a TOTP code generated from a base32 secret.

Changes

  • Add otplib@12 as a dev dep (v13 reworked the API surface entirely; v12 has stable authenticator.generate(secret) plus deprecation notices that are noise at this scale of consumer).
  • lib/env.ts: new required totpSecret field reading E2E_TOTP_SECRET (base32, what you originally pasted into your authenticator app). Preflight aggregator includes it.
  • lib/login.ts: after the password submit, waitForURL(/\/login\/(2fa|mfa)/); if matched, generate the current TOTP code, fill the second-factor form (permissive selectors: data-testid="totp", autocomplete="one-time-code", name="code|otp|totp", inputmode="numeric"), click Verify/Continue/Submit.
  • Widen the /login regex on the post-login poll AND on expectAtLoginScreen to /^\/login(\/|$)/ so /login/2fa, /login/mfa, /login/recovery etc count as IN /login. Same regex change as PR #105; subsumes it.
  • .env.example + README.md document E2E_TOTP_SECRET and the provisioning step.

Operator step

Add E2E_TOTP_SECRET to Forgejo Actions secrets before the next run (the base32 string saved at 2FA enrollment for the E2E account). Preflight will name it explicitly if missing.

Test plan

  • Add E2E_TOTP_SECRET to Forgejo secrets. Merge. The next E2E run should clear setup (token captured) and auth-ui (URL settles past /login/2fa).
  • If the hub's 2FA input selector doesn't match any of the permissive locators, the next failure will say locator.waitFor: timeout on fillTotpStep, and we tighten the selector list.
## Summary The staging E2E account has 2FA enabled. The bunyip hub redirects to `/login/2fa` after a credentials submit; the previous `loginViaSpa` stopped at credentials and let the helper return false-success, so the downstream bearer capture had nothing to grab. This PR drives the second factor end-to-end with a TOTP code generated from a base32 secret. ### Changes - Add `otplib@12` as a dev dep (v13 reworked the API surface entirely; v12 has stable `authenticator.generate(secret)` plus deprecation notices that are noise at this scale of consumer). - `lib/env.ts`: new required `totpSecret` field reading `E2E_TOTP_SECRET` (base32, what you originally pasted into your authenticator app). Preflight aggregator includes it. - `lib/login.ts`: after the password submit, `waitForURL(/\/login\/(2fa|mfa)/)`; if matched, generate the current TOTP code, fill the second-factor form (permissive selectors: `data-testid="totp"`, `autocomplete="one-time-code"`, `name="code|otp|totp"`, `inputmode="numeric"`), click Verify/Continue/Submit. - Widen the `/login` regex on the post-login poll AND on `expectAtLoginScreen` to `/^\/login(\/|$)/` so `/login/2fa`, `/login/mfa`, `/login/recovery` etc count as IN `/login`. Same regex change as PR #105; subsumes it. - `.env.example` + `README.md` document `E2E_TOTP_SECRET` and the provisioning step. ### Operator step Add `E2E_TOTP_SECRET` to Forgejo Actions secrets before the next run (the base32 string saved at 2FA enrollment for the E2E account). Preflight will name it explicitly if missing. ## Test plan - [ ] Add `E2E_TOTP_SECRET` to Forgejo secrets. Merge. The next E2E run should clear setup (token captured) and auth-ui (URL settles past `/login/2fa`). - [ ] If the hub's 2FA input selector doesn't match any of the permissive locators, the next failure will say `locator.waitFor: timeout` on `fillTotpStep`, and we tighten the selector list.
nrupard force-pushed feat/e2e-totp-handling from 33ca0b9804
All checks were successful
Check / fmt + clippy + compile + tests (pull_request) Successful in 56s
to 1a9e37e6e1
All checks were successful
Check / fmt + clippy + compile + tests (pull_request) Successful in 1m24s
Create release / Create release from merged PR (pull_request) Has been skipped
2026-06-05 18:32:36 +02:00
Compare
nrupard deleted branch feat/e2e-totp-handling 2026-06-05 18:34:28 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!106
No description provided.