ClubSpark Classic Auth — Stage/Test pre-rollout baseline
Captured: 2026-07-09 · Strengthened + re-captured: 2026-07-10 (stage & test rolled back to pre-rollout) · Harness: pw-harness (Playwright) · Scope: sign-up / sign-out / sign-in across the classic (legacy WS-Federation) identity platform on the stage & test tiers.
This is a pre-rollout baseline: re-run the identical commands after the deployment and diff the results. Any change from this baseline is a regression (was ✅, now ❌) or an improvement (was ❌/⛔, now ✅).
🔎 Final-destination checks (what each flow lands on)
Earlier runs only asked “are we signed in / signed out?” — they force-navigated back to the venue to check session state, which masked where each flow actually left the browser. This capture asserts the natural final URL of every sign-up, sign-out and sign-in — the page you actually land on, captured before any corrective navigation — and, new in this revision, saves a landing-page screenshot of every step so you can see exactly what rendered after signup, signout and signin.
A shared classifier (classifyLanding) decides returned-to-venue vs stranded using the landing host + path (ignoring query/fragment token material, since an OIDC response fragment can contain substrings like okta/logout). Sign-out has two expected outcomes, both PASS: the top-level venue redirects to the venue home, while sub-venues / custom domains come to rest on a branded “You have been signed out” confirmation page (served from the WS-Fed sign-out endpoint) — this is by design; only an error page or unexpected location fails.
Result summary
Legend: ✅ pass · ❌ fail · ⛔ blocked (external/pre-existing) · ➖ n/a · ⚠️ partial
| # | Domain | Auth path | Sign up → dest | Sign out → dest | Sign in → dest | Overall |
|---|---|---|---|---|---|---|
| 1 | stg-solo-web.clubspark.io/ |
Legacy WS-Fed, local form | ✅ venue | ✅ venue home | ✅ venue | 10/10 PASS |
| 2 | stg-solo-web.clubspark.io/RITUVENUES/ |
Legacy WS-Fed (sub-venue) | ✅ venue | ✅ sign-out page* | ✅ venue | 10/10 PASS |
| 3 | stg-solo-custom.clubspark.ninja/ |
Legacy WS-Fed (custom domain) | ✅ venue | ✅ sign-out page* | ✅ venue | 10/10 PASS |
| 4 | tst-fa-web.clubspark.io/ |
Legacy WS-Fed → Azure B2C | ➖ FA’s own RP† | ✅ venue | ❌ stalls on B2C | 5/7 — Finding |
| 5 | stg-ecb2-web.clubspark.io/ |
Legacy WS-Fed → ECB Okta | ✅ venue | ✅ venue | ✅ venue | 7/7 PASS |
| 6 | stage-lta.clubspark.io/ |
Legacy WS-Fed, local; external signup | ⛔ | ➖ | ⚠️ form only | see §6 |
| 7 | stg-fa-web.clubspark.io/ |
Legacy WS-Fed → Azure B2C | ❌ wrong RP | ✅ venue | ❌ stalls on B2C | 5/7 — §7 |
* Sub-venue / custom-domain sign-out lands on the expected “You have been signed out” confirmation page (not the venue home) — a PASS, per above. † FA’s hosted create-account journey returns to FA’s own relying party by design — reported as INFO, not asserted against the venue.
Solo (§1–3) and ECB (§5) return the user to the right place on every action. The only functional failure is FA sign-in (§4/§7), which stalls inside B2C and never comes back — see the Finding. (§7 additionally can’t sign up, due to the pre-existing wrong-RP issue.)
🚩 Finding — FA sign-in (MFA) stalls on B2C and never returns to the venue
On tst-fa-web (§4) and stg-fa-web (§7), FA sign-in uses the MFA policy b2c_1a_signup_signinmfa. The harness signs in and the email MFA code is entered, but the flow then parks on the B2C England-Football page:
https://b2cqathefa.b2clogin.com/…/b2c_1a_signup_signinmfa/api/CombinedSigninAndSignup/confirmed?…
and never federates back to the venue (see the after sign in screenshot in §4). The B2C diagnostics place the stall at a custom FA orchestration step (T021 → https://qab2cstore.thefa.com/b2cact/indexCS.html?FAAppToken=CS&ClientId=…) — an FA “app token” exchange — that does not complete, so B2C never issues the token to the relying party.
Determined to be an FA-side (environment) issue, not a harness issue: clicking the primary button on that page produces no navigation (verified waiting up to 20s per click), and simply waiting (~200s) does not federate out either. FA sign-up through B2C (a different policy) completes fine, and FA sign-out returns to the venue — only the sign-in MFA orchestration stalls. This is the class of FA dependency that is outside ClubSpark’s control. (It did complete at the original 2026-07-09 capture, so the FA app-token step has since regressed or the rollback didn’t restore it.) The harness auto-detects the MFA step and supplies the code, then reports the stall via the final-URL check rather than hanging silently.
How to reproduce
cd pw-harness && npm install # downloads Chromium on first run
.env carries CS_BASE, CS_LEGACY_AUTH_HOST, CS_EMAIL_DOMAIN=clubspark.dev (whitelisted so B2C/ECB OTP + activation emails reach Mailpit), and MAILPIT_*. Each suite prints a PASS/FAIL line per assertion — including … returned to venue (final URL) / … signout landed correctly — and exits non-zero on any failure. Set CS_LANDING_DIR=<dir> to save the per-step landing screenshots shown below.
§1–3 · Solo / Independent — ✅ fully passing
All three share /Account/SignIn → stg-solo-auth.clubspark.io/issue/wsfed → a local EmailAddress/Password form with a self-serve Register link.
CS_BASE=https://stg-solo-web.clubspark.io/ CS_LEGACY_AUTH_HOST=stg-solo-auth.clubspark.io node test-legacy-auth.mjs 1 # §1 → 10/10 ✅
CS_BASE=https://stg-solo-web.clubspark.io/RITUVENUES/ CS_LEGACY_AUTH_HOST=stg-solo-auth.clubspark.io node test-legacy-auth.mjs 1 # §2 → 10/10 ✅
CS_BASE=https://stg-solo-custom.clubspark.ninja/ CS_LEGACY_AUTH_HOST=stg-solo-auth.clubspark.io node test-legacy-auth.mjs 1 # §3 → 10/10 ✅
§1 · stg-solo-web (top-level) — video
Landing pages (click to enlarge):
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
✅ venue …clubspark.io/ |
✅ venue home …clubspark.io/ |
✅ venue …clubspark.io/ |
§2 · stg-solo-web /RITUVENUES (sub-venue) — video
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
✅ …/RITUVENUES/ |
✅ “You have been signed out” (expected) | ✅ …/RITUVENUES/ |
§3 · stg-solo-custom.clubspark.ninja (custom domain) — video
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
✅ …clubspark.ninja/ |
✅ “You have been signed out” (expected) | ✅ …clubspark.ninja/ |
§4 · tst-fa-web (The FA) — sign-in stalls on B2C (Finding)
/Account/SignIn → stg-solo-auth → HRD idp=duende → stg-solo-ids-sts → Azure B2C (b2cqathefa.b2clogin.com). Email OTP (verification + MFA) is read from Mailpit.
node fa-suite.mjs https://tst-fa-web.clubspark.io/ 1 # 5/7
signup — video
signin + signout — video
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
➖ FA’s own RP tst-solo-auth (by design) |
✅ venue tst-fa-web…/ |
❌ stuck on B2C (England Football verification / confirmed) — never returns to the venue |
§5 · stg-ecb2-web (ECB) — ✅ returns to venue on every action
/Account/SignIn → stg-solo-auth → HRD idp=ecb → stg-solo-ids-sts → ECB Okta → ECB “myaccount” SPA. Homepage redirects to /AllStars/Search.
CS_BASE=https://stg-ecb2-web.clubspark.io/ node test-ecb-auth.mjs 1 # 7/7 ✅
signup — video
signin + signout — video
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
✅ …/AllStars/Search |
✅ …/AllStars/Search |
✅ …/AllStars/Search |
Sign-in ticks the “Confirm Your Preferences” consent modal to resume the federation; the harness auto-detects that ECB sign-in currently requires no MFA (it handles it if turned on). The sign-up landing carries an OIDC token fragment (#id_token=…okta.users…) — the classifier correctly treats this as a venue landing (it inspects host + path, not the token fragment).
§6 · stage-lta (LTA) — ⛔ signup external (reCAPTCHA); signin needs a seed account
/Account/SignIn → stage-lta-auth.clubspark.io → local EmailAddress/Password form (“Login”). Registration is delegated to https://www.lta.org.uk/register behind Google reCAPTCHA.
CS_BASE=https://stage-lta.clubspark.io/ CS_LEGACY_AUTH_HOST=stage-lta-auth.clubspark.io node test-lta-auth.mjs 1
# with a seed account (exercises the final-URL checks + landing shots): LTA_EMAIL=… LTA_PASSWORD=… …same…
- Sign up ⛔ (by design): reaches the lta.org.uk form and stops at the
g-recaptcha-responsewall. - Sign in ⚠️: the LTA credential form is reachable on
stage-lta-auth; with no seed credentials a login can’t complete, so the final-URL check / landing screenshots are not exercised. - Sign out ➖: not reachable without a completed login.
Videos retained from the prior capture (LTA is unchanged by the final-URL work — external/reCAPTCHA-gated, no landing checks without seed creds).
§6 · LTA register → reCAPTCHA wall — direct link
§6 · LTA signin form (reachability) — direct link
§7 · stg-fa-web (The FA) — wrong-RP signup + B2C sign-in stall
Same B2C topology as §4, but the “CREATE AN ACCOUNT” journey federates back to tst-solo-ids-sts (a cross-env mismatch), so sign-up ❌ can’t complete against STG. Sign-in ❌ hits the same FA app-token stall as §4 (Finding). Sign-out ✅ returns to stg-fa-web.clubspark.io/.
node fa-suite.mjs https://stg-fa-web.clubspark.io/ 1 # 5/7
signup — video
signin + signout — video
| after sign up | after sign out | after sign in |
|---|---|---|
![]() |
![]() |
![]() |
| ❌ FA’s tst RP (cross-env mismatch) | ✅ venue stg-fa-web…/ |
❌ stuck on B2C — never returns to the venue |
Harness changes behind this baseline
- Final-destination assertions + landing screenshots (new):
classifyLanding(url, venue)+ alandedUrlcaptured at the natural end of every flow before any corrective navigation, plus a full-page screenshot per step (CS_LANDING_DIR). Sign-out accepts both expected outcomes — venue home (top-level) or the “You have been signed out” confirmation page (sub-venues / custom domains) — and fails only on an error/unexpected landing. - MFA auto-detection + step logging: FA (B2C) and ECB (Okta) sign-in detect at runtime whether an email-code step is required and drive it, with timestamped
[HH:MM:SS] <flow>: <step> @ <url>logs — this is how the FA app-token stall was localised. - Robustness: bounded field-fill clicks and bounded LTA navigations so a slow/covered external form can’t hang a run.
- Cross-platform / env-driven hosts (from the original capture):
.envviafileURLToPath;CS_LEGACY_AUTH_HOST+CS_EMAIL_DOMAIN;WEB_HOSTderives fromCS_BASE.
Post-deploy checklist
Re-run each command above and compare to this baseline:
- §1–3 solo / venue / custom — must stay 10/10 each: signup + signin return to the venue; sign-out returns to the venue home (top-level) or the “You have been signed out” page (venue/custom). Any FAIL = regression.
- §5 stg-ecb2-web — must stay 7/7, all actions returning to
/AllStars/Search. - §4 / §7 FA — sign-in is currently ❌ (FA app-token stall) — if it turns ✅, the FA orchestration recovered. §7 sign-up stays ❌ until its B2C RP is repointed off tst.
- §6 stage-lta — sign-up stays ⛔ (reCAPTCHA); supply seed creds to baseline the signin/signout final URLs + landing shots.

















