fix(auth): point OIDC issuer at auth.berget.ai after Keycloak cutover - #89
Conversation
Follow-up to incident 2026-09-10-0: token issuance moved from keycloak.berget.ai to auth.berget.ai. The CLI still discovered and refreshed against the legacy hostname, which breaks PKCE login (strict-iss validation since the auth-server 301:es legacy requests) and token refresh (Keycloak 26.6 requires mint-host == refresh-host, invalid_grant on every existing session). Flip prod to auth.berget.ai and stage/local to auth.stage.berget.ai.
There was a problem hiding this comment.
Review
Summary
This PR migrates the CLI's Keycloak hostname from keycloak.berget.ai / keycloak.stage.berget.ai to auth.berget.ai / auth.stage.berget.ai in getAuthConfig() and updates the corresponding unit tests.
Risk
LOW — A pure string-hostname migration with tests updated; I verified both new hosts are live and serve correct OIDC discovery metadata (see below), so discovery/realm construction ({keycloakUrl}/realms/berget) will resolve and the reported issuer matches exactly what the CLI builds.
Verification performed
https://auth.berget.ai/realms/berget/.well-known/openid-configuration→ HTTP 200,issuer: https://auth.berget.ai/realms/berget✅https://auth.stage.berget.ai/realms/berget/.well-known/openid-configuration→ HTTP 200,issuer: https://auth.stage.berget.ai/realms/berget✅- No docs, README, or non-test code still references the old
keycloak.berget.aihost. keycloakUrlflows only intosrc/auth/issuer.ts(discovery, keyed by issuer URL — in-memory cache, so no stale state across versions) andsrc/auth/credentials/resolver.ts(refresh path). The old hostname remains only inissuer.test.ts,pkce-flow.test.ts, andtoken-refresh.test.tsfixtures, but those pass explicit URLs and are self-consistent mocks, so tests do not break.
Issues
- None on the changed lines.
- nit (unchanged files, prose-only) —
src/auth/__tests__/issuer.test.ts,pkce-flow.test.ts, andtoken-refresh.test.tsstill usekeycloak.berget.aias fixture values whileconfig.tsnow canonicalizesauth.berget.ai; harmless because they inject their own URLs, but the fixtures no longer mirror the real prod issuer.
Suggestions
src/auth/__tests__/issuer.test.ts— consider aligning fixture hostnames with the newauth.berget.aiso future readers don't assume the old host is still valid.- Migration note for release notes: users with a stored refresh token issued against the old host will now refresh via
auth.berget.ai; if the realm/keys were carried over (discovery is live, suggesting yes) refresh continues seamlessly, otherwise users re-authenticate once.
Architecture
No structural change — this is a hostname constant rotation in the single auth-config source of truth, with all consumers deriving from getAuthConfig().
CodeSense: 9/10 — minimal, single-source-of-truth change with full test coverage of every branch; only deduction is the inconsistency with old fixtures in neighboring test files.
Inline findings
Berget AI (berget/zai-org/GLM-5.3-Flash) | PR #89
| } else { | ||
| apiBaseUrl = 'https://api.berget.ai'; | ||
| keycloakUrl = 'https://keycloak.berget.ai'; | ||
| keycloakUrl = 'https://auth.berget.ai'; |
There was a problem hiding this comment.
✅ good — Verified live: https://auth.berget.ai/realms/berget serves OIDC discovery with issuer matching this URL.
| // Infer keycloak from API URL for custom endpoints | ||
| if (apiBaseUrl.includes('localhost') || apiBaseUrl.includes('stage.')) { | ||
| keycloakUrl = 'https://keycloak.stage.berget.ai'; | ||
| keycloakUrl = 'https://auth.stage.berget.ai'; |
There was a problem hiding this comment.
✅ good — Verified live: https://auth.stage.berget.ai/realms/berget serves OIDC discovery for realm 'berget'.
| const config = getAuthConfig(); | ||
| expect(config.apiBaseUrl).toBe('https://api.berget.ai'); | ||
| expect(config.keycloakUrl).toBe('https://keycloak.berget.ai'); | ||
| expect(config.keycloakUrl).toBe('https://auth.berget.ai'); |
There was a problem hiding this comment.
✅ good — All config branches (default, stage, local, env-override) covered with the new hostname.
Hygiene after the issuer migration: make the auth test fixtures mirror the real prod/stage issuers (auth.berget.ai, auth.stage.berget.ai) so no stale hostname references linger. No behavior change.
There was a problem hiding this comment.
Follow-up review
New changes: 1 commit (d002083) — mechanical string swap of keycloak[.stage].berget.ai → auth[.stage].berget.ai in the three test-fixture files.
Previous findings:
- ✅ nit #1 fixed — all three test files (
issuer.test.ts,pkce-flow.test.ts,token-refresh.test.ts) now useauth.*issuers; repo-wide grep confirms zero remaining references to the oldkeycloak.*.berget.aihosts. - ✅ Suggestion applied — fixtures now mirror the canonical hostnames held by
config.ts(verified atsrc/auth/config.ts:23-35).
New findings: None. The diff touches only fixture string literals; in each file the swaps are internally consistent (e.g. in pkce-flow.test.ts the iss callback param now matches the mocked buildAuthorizationUrl URL, and in token-refresh.test.ts the prod/stage pair remains distinct so the dedup assertions still exercise the same code paths). Test semantics and coverage are unchanged.
Berget AI (berget/zai-org/GLM-5.3-Flash) | PR #89
Ändring
Flippa CLI:ns OIDC-issuer från gamla
keycloak.berget.ai→auth.berget.ai(prod) ochkeycloak.stage.berget.ai→auth.stage.berget.ai(stage/local), efter Keycloak-cutovern.Bakgrund
Updaterat i incidenten 2026-09-10-0-oidc-issuer-migration-fallout: token-issuance flyttades till
auth.berget.ai, legacy-hosten 301:as och tokens mintas mediss=https://auth.berget.ai/realms/berget. CLI:n pekade fortfarande på gamla hostname:en, vilket ger:issstrikt (callback-iss trap, incident lesson Fix/model list #4).invalid_grant→ tokens rensas → tvingad re-login (detsamma som api-sub-incidenten, fixad i api #453).Alla andra klienter (console, backend-api, infra/cli) är redan flippade; detta var eftersläpande i
cli.Test
npx vitest run— 265 tester passerar (uppdateradeconfig.test.tsmed nya URL:er)npx tsc --noEmitrentObs: existerande CLI-sessioner med refresh-tokens mintade på gamla hosten kommer tvingas re-logga en gång (samma beteende som console-användarna fick i incidenten).