Skip to content

fix(auth): point OIDC issuer at auth.berget.ai after Keycloak cutover - #89

Merged
bergetjakob merged 2 commits into
mainfrom
fix/auth-issuer-migration
Sep 11, 2026
Merged

bergetjakob merged 2 commits into
mainfrom
fix/auth-issuer-migration

Conversation

@bergetjakob

Copy link
Copy Markdown
Contributor

Ändring

Flippa CLI:ns OIDC-issuer från gamla keycloak.berget.aiauth.berget.ai (prod) och keycloak.stage.berget.aiauth.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 med iss=https://auth.berget.ai/realms/berget. CLI:n pekade fortfarande på gamla hostname:en, vilket ger:

  1. Kaputt PKCE-login — openid-client v6 validerar iss strikt (callback-iss trap, incident lesson Fix/model list #4).
  2. Kaputt token-refresh — Keycloak 26.6 kräver mint-host == refresh-host → 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 (uppdaterade config.test.ts med nya URL:er)
  • npx tsc --noEmit rent

Obs: 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).

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.
berget-ai[bot]
berget-ai Bot previously approved these changes Sep 11, 2026

@berget-ai berget-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ai host.
  • keycloakUrl flows only into src/auth/issuer.ts (discovery, keyed by issuer URL — in-memory cache, so no stale state across versions) and src/auth/credentials/resolver.ts (refresh path). The old hostname remains only in issuer.test.ts, pkce-flow.test.ts, and token-refresh.test.ts fixtures, 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, and token-refresh.test.ts still use keycloak.berget.ai as fixture values while config.ts now canonicalizes auth.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 new auth.berget.ai so 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

Comment thread src/auth/config.ts
} else {
apiBaseUrl = 'https://api.berget.ai';
keycloakUrl = 'https://keycloak.berget.ai';
keycloakUrl = 'https://auth.berget.ai';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good — Verified live: https://auth.berget.ai/realms/berget serves OIDC discovery with issuer matching this URL.

Comment thread src/auth/config.ts
// 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';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@berget-ai berget-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review

New changes: 1 commit (d002083) — mechanical string swap of keycloak[.stage].berget.aiauth[.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 use auth.* issuers; repo-wide grep confirms zero remaining references to the old keycloak.*.berget.ai hosts.
  • ✅ Suggestion applied — fixtures now mirror the canonical hostnames held by config.ts (verified at src/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

@bergetjakob
bergetjakob merged commit 3af9433 into main Sep 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant