fix(e2e): handle the OIDC consent screen in loginViaSpa (PMS-521) #365

Merged
nrupard merged 1 commit from fix/PMS-521-loginviaspa-consent into main 2026-06-25 22:58:48 +02:00
Owner

What

Fixes PMS-521: the e2e setup login (and therefore the whole suite) was failing because the staging OP now routes the post-2FA authorize through /oauth2/consent.

Root cause

The SPA requests scope=openid email offline_access profile, but the E2E account never granted profile, so the OP 302s authorize to /oauth2/consent?missing=profile. loginViaSpa had no consent step, so the flow looped (authorize -> consent -> app shell -> authorize -> consent), /oauth2/token never fired, and setup captured no bearer. setup failing fails everything (auth-ui, form-ui, and every api spec depend on its login/bearer).

Diagnosed from e2e run #2522 (PR #364): postLoginUrl=/oauth2/consent?missing=profile, scope=...profile, "OIDC token exchange never fired".

Fix

loginViaSpa's post-login navigation wait now clicks Allow whenever the page lands on /oauth2/consent. The grant POSTs to bunyip-api and persists, so subsequent authorize calls skip consent and the token exchange fires. Any /login* path is still treated as in-flow; a 30s deadline throws a clear message naming the consent markup if the selector ever moves.

Selector mirrors bunyip's own e2e driveConsent and bunyip-web/src/handlers/consent.rs: button[name="action"][value="allow"], with a getByRole('button', { name: /allow|authorize|approve/i }) fallback.

Verification

This PR's e2e run against staging is the verification - setup should now log in (look for [setup] captured bearer from ...) and the api specs should run. (The auth-ui + form-ui specs stay test.fixme on main; re-verifying those is PMS-519, on #364, once this lands.)

npx playwright test --list compiles clean.

## What Fixes **PMS-521**: the e2e `setup` login (and therefore the whole suite) was failing because the staging OP now routes the post-2FA authorize through `/oauth2/consent`. ## Root cause The SPA requests `scope=openid email offline_access profile`, but the E2E account never granted `profile`, so the OP 302s authorize to `/oauth2/consent?missing=profile`. `loginViaSpa` had no consent step, so the flow looped (authorize -> consent -> app shell -> authorize -> consent), `/oauth2/token` never fired, and `setup` captured no bearer. `setup` failing fails everything (`auth-ui`, `form-ui`, and every `api` spec depend on its login/bearer). Diagnosed from e2e run #2522 (PR #364): `postLoginUrl=/oauth2/consent?missing=profile`, `scope=...profile`, "OIDC token exchange never fired". ## Fix `loginViaSpa`'s post-login navigation wait now clicks **Allow** whenever the page lands on `/oauth2/consent`. The grant POSTs to bunyip-api and persists, so subsequent authorize calls skip consent and the token exchange fires. Any `/login*` path is still treated as in-flow; a 30s deadline throws a clear message naming the consent markup if the selector ever moves. Selector mirrors bunyip's own e2e `driveConsent` and `bunyip-web/src/handlers/consent.rs`: `button[name="action"][value="allow"]`, with a `getByRole('button', { name: /allow|authorize|approve/i })` fallback. ## Verification This PR's **e2e run against staging is the verification** - `setup` should now log in (look for `[setup] captured bearer from ...`) and the `api` specs should run. (The `auth-ui` + `form-ui` specs stay `test.fixme` on `main`; re-verifying those is PMS-519, on #364, once this lands.) `npx playwright test --list` compiles clean.
fix(e2e): handle the OIDC consent screen in loginViaSpa (PMS-521)
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 55s
Check / fmt + clippy + build + tests (pull_request) Successful in 2m52s
Integration / integration tests (pull_request) Successful in 12m31s
Create release / Create release from merged PR (pull_request) Successful in 4s
25c1ea390d
The staging OP now routes the post-2FA authorize through /oauth2/consent because the SPA requests the `profile` scope and the E2E account has not granted it. loginViaSpa had no step for the consent screen, so authorize looped (authorize -> consent -> app shell -> authorize -> consent), the token exchange never fired, and `setup` captured no bearer - failing setup and, with it, the entire suite (auth-ui, form-ui, and every api spec depend on setup's login/bearer).

Diagnosed from e2e run #2522 (PR #364): setup's diagnostic showed postLoginUrl=/oauth2/consent?missing=profile, scope=openid+email+offline_access+profile, and "OIDC token exchange never fired".

Fix: in loginViaSpa's post-login navigation wait, click Allow whenever the page lands on /oauth2/consent (the grant POSTs to bunyip-api and persists, so later authorize calls skip consent), and keep treating any /login* path as still-in-flow. Mirrors bunyip's e2e driveConsent and bunyip-web/src/handlers/consent.rs (the Allow control is `button[name="action"][value="allow"]`, with a text/role fallback). Best-effort click + a 30s overall deadline with a clear timeout message naming the consent markup if the selector ever moves.

This un-breaks `setup` (and the always-on api specs); the still-quarantined auth-ui + form-ui specs (PMS-519) can be re-verified once this lands.

#PMS-521
nrupard deleted branch fix/PMS-521-loginviaspa-consent 2026-06-25 22:58:48 +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!365
No description provided.