Repository navigation
test(e2e): OIDC sign-in against a mock IdP (compose override + Playwright spec) - #440
Merged
Merged
Conversation
…ight spec) docker-compose.oidc-e2e.yml adds navikt/mock-oauth2-server 6.1.3 in the backend's network namespace, so http://localhost:8080/ganek is the same issuer for the backend and the browser, and points GANEK_OIDC_* at it. frontend/e2e/sso.spec.ts signs the suite's admin in through "Continue with Mock IdP" and accepts a team invite through SSO; it skips unless E2E_OIDC=1, so the default E2E run is unchanged. Production compose and .env.example are untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPybyvkbTrgrgAQHfjyJQ3
The 2026-11-09 16:00-18:00 UTC GitHub brownout blocked the cla workflow at startup; an empty commit re-sends the pull_request_target event. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Board card: E2E: OIDC sign-in against a mock IdP (compose override + Playwright test) (PVTI_lADOElDmdM4Bn50jzhHLapk)
Draft card, so no
Closes. Closes the last AC of the parent card "SSO + multi-company user membership" ("OIDC login works against a test IdP in e2e"), following the owner decision of 2026-11-09 (option b in #430: mock IdP from a separate, E2E-only compose file).Research
issueragainstGANEK_OIDC_ISSUER, requires https endpoints except onlocalhost/127.0.0.1, checksaud/azp= client id, nonce, and does PKCE. Invite accept through OIDC (feat(auth): accept a team invite through the instance's OIDC provider #430) needs the IdP to vouch for the invited email (email_verified). Team invite links are only emailed, never returned by the API.JSON_CONFIGthe standalone server enables an interactive login page (username becomessub, a claims JSON box adds claims), verifies PKCE, echoes the nonce, sets the ID tokenaudto the client id andazpto the client id, and derives the issuer (http://<host>/<issuerId>) from the request host. 6.1.3 (2026-10-23) is pinned; its release workflow publishedghcr.io/navikt/mock-oauth2-server:6.1.3successfully.oidc-provider-mock. The recurring pain point in self-hosted SSO threads (Vikunja, BookStack, Zitadel issues) is the issuer mismatch between the hostname the browser sees and the one the container sees. This override avoids it by construction: the mock IdP shares the backend's network namespace, sohttp://localhost:8080/ganekis the same IdP for the backend (discovery, token exchange) and for the browser (login page, through a port published on the backend), and it satisfies our "https or localhost" endpoint rule without loosening it.Plan and scope
docker-compose.oidc-e2e.yml:mock-idpservice (pinned image,network_mode: service:backend), plusGANEK_OIDC_*for the backend (issuerhttp://localhost:8080/ganek, clientganek-e2e, display name "Mock IdP", email domaine2e.ganek.dev) and a loopback-only127.0.0.1:8080port on the backend for the browser.frontend/e2e/sso.spec.ts(runs last, alphabetical, workers=1):/login-> "Continue with Mock IdP" -> mock login as the suite admin (verified email) -> lands on/admin;/api/v1/auth/meshows the admin withsso_linked. First run links by verified email, reruns sign in by (issuer, sub)./invite/<token>-> "Continue with Mock IdP" -> lands on/adminas the new teammate (rolemember,sso_linked, no password). Unique email per run, so reruns on the same stack work.frontend/e2e/invite-token.ts: signs the invite token exactly likecreate_invite_token(itsdangerousURLSafeTimedSerializer, saltganek-team-invite) with the stack'sGANEK_SECRET_KEY(fromE2E_SECRET_KEY, else the repo-root.envthat compose gave the backend; CI copies.env.example). Needed because invite links are never exposed by the API.E2E_OIDC=1; when set it waits for the IdP's discovery document (JVM start) and then requires the SSO button.In scope: the above. Out of scope: SAML (own card), production
docker-compose.yml/.env.example(untouched),scripts/ci_local.sh(can mirror the lines below once the workflow has them),.github/workflows/(owner edits, below).Acceptance:
browserjob runs the two SSO tests.sso.spec.tsis skipped (the defaultdocker compose upstack has noGANEK_OIDC_*andE2E_OIDCis unset).docker-compose.ymland.env.exampleuntouched.Workflow lines for the owner (
.github/workflows/e2e.yml)Task PRs never edit workflows. To turn the spec on, add a job-level
envto thebrowserjob only (leavecompose-smokeas is).COMPOSE_FILEmakes everydocker composecall in that job (up, ps, logs) use both files, so the failure log dump also covers the IdP:Testing
pnpm typecheckOK;pnpm lint0 errors (3 pre-existing warnings);pnpm exec playwright test --listlists the two SSO tests next to the existing specs. Vitest only collectssrc/**and is unaffected.signInviteTokencross-checked against Pythonitsdangerous:URLSafeTimedSerializer(..., salt="ganek-team-invite").loads()accepts the Node-minted token, anddumps()of the same id in the same second gives a byte-identical token.docker compose -f docker-compose.yml -f docker-compose.oidc-e2e.yml configresolves: backend gets the fiveGANEK_OIDC_*vars and ports 8000 + 8080 on 127.0.0.1,mock-idpruns inservice:backend; plaindocker compose confighas nomock-idp.input[name=username],textarea[name=claims], "Sign-in" button) and claim behaviour were read from the 6.1.3 source (login.ftl,AuthorizationCodeHandler,OAuth2TokenProvider). The first real run is the E2E job once the lines above are added; in this PR's CI the spec is skipped by design.git diff --cached | md5sum59e0b206... on both sides.🤖 Generated with Claude Code
https://claude.ai/code/session_01RPybyvkbTrgrgAQHfjyJQ3
Status (run 2026-11-09 ~17:35 UTC) - blocked, needs the owner
CI (all 7 jobs), E2E (the new SSO spec skips by design until the workflow lines above are added) and the auto-merge workflow are green and
auto_mergeis enabled, but GitHub has not merged: the ruleset requires thecla-assistantcheck and theclaworkflow ended in startup_failure with no jobs (run 42662750137). Same blocker as #439: everyclarun since 16:15 UTC has failed to start, the last success was 15:16 UTC on #438. Not merged by hand and no workflow edited, per the task rules. To unblock: open the cla run page for the startup error (or commentrecheck), then the PR merges itself once the check is green. Card set to In review.