Why β this blocks all test-automation PBIs
Every testing initiative is stuck on the same first step: tests can't log in without a human, a browser, or real staging credentials.
This PBI delivers the shared auth foundation β a generic test user that works non-interactively across the API and AdminUI β so e2e suites and AI agents (CI, Claude, Codex, Copilot) can authenticate with one command and zero secrets.
β Blocks:
The design (validated)
Internal research (incl. an independently reviewed .NET 10 spike β 8/8 auth assertions passing) landed on:
A test access-token the API trusts is the universal login. Add a dev/test-only signing key that the API trusts only under a Testing profile, and a helper that mints a rewards-audience JWT offline with arbitrary claims (sub, email, role=Admin). Every test surface then authenticates with no IdP, no browser, no network, no secrets.
- API e2e β send the minted token as
Authorization: Bearer β exercises the real controller pipeline incl. [Authorize(Roles = "Admin")] (today's integration tests bypass this by mocking ICurrentUserService).
- AdminUI e2e β Blazor WASM does a real auth-code+PKCE redirect, so Playwright drives login against a pinned local SSW.IdentityServer with a seeded admin user (reuses the existing
tools/ui-tests harness β just an authority swap; no staging, no real creds).
Scope
Out of scope
Security guardrail (non-negotiable)
The test key must be worthless against Production: trust is gated to the Testing environment with a fail-fast startup check, Production/Staging keep real OIDC validation only, and the design is documented in the API so a future change can't silently widen trust.
Why β this blocks all test-automation PBIs
Every testing initiative is stuck on the same first step: tests can't log in without a human, a browser, or real staging credentials.
This PBI delivers the shared auth foundation β a generic test user that works non-interactively across the API and AdminUI β so e2e suites and AI agents (CI, Claude, Codex, Copilot) can authenticate with one command and zero secrets.
β Blocks:
The design (validated)
Internal research (incl. an independently reviewed .NET 10 spike β 8/8 auth assertions passing) landed on:
Authorization: Bearerβ exercises the real controller pipeline incl.[Authorize(Roles = "Admin")](today's integration tests bypass this by mockingICurrentUserService).tools/ui-testsharness β just an authority swap; no staging, no real creds).Scope
ASPNETCORE_ENVIRONMENT=Testing; if the flag is set under any other environment (incl. Staging) the API fails fast at startup. Issuer validation stays ON (append a fixed test issuer β neverValidateIssuer=false). No live OIDC metadata fetch on this path (static configuration so validation is fully offline). Asymmetric keypair: API trusts only the public key.TestTokenFactory/ small CLI):aud=rewards, headertyp=at+jwt, claimssub/email/role. Generic test user identity is deterministic + documented.WebApplicationFactory-based tests hitting real controllers with the minted token β positive (user + admin) and negative (no token, unknown key, wrong audience, flag off β all 401).tools/ui-testsPlaywrightauth.setup.tsauthenticates against local IdentityServer (pinned port) with the seeded admin β full suite green locally with no staging dependency.Out of scope
sswrewards://autologin?token=β¦deep link makes the same token work on iOS/Android, but the mobile team is busy; follow-up under π οΈ API/Mobile | TestingΒ #869.Security guardrail (non-negotiable)
The test key must be worthless against Production: trust is gated to the Testing environment with a fail-fast startup check, Production/Staging keep real OIDC validation only, and the design is documented in the API so a future change can't silently widen trust.