Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/auth/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ describe('getAuthConfig', () => {
it('returns production URLs by default', () => {
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.

expect(config.realm).toBe('berget');
expect(config.clientId).toBe('berget-code');
});

it('returns stage URLs when stage: true', () => {
const config = getAuthConfig({ stage: true });
expect(config.apiBaseUrl).toBe('https://api.stage.berget.ai');
expect(config.keycloakUrl).toBe('https://keycloak.stage.berget.ai');
expect(config.keycloakUrl).toBe('https://auth.stage.berget.ai');
});

it('returns local URLs when local: true', () => {
const config = getAuthConfig({ local: true });
expect(config.apiBaseUrl).toBe('http://localhost:3000');
expect(config.keycloakUrl).toBe('https://keycloak.stage.berget.ai');
expect(config.keycloakUrl).toBe('https://auth.stage.berget.ai');
});

it('overrides apiBaseUrl with BERGET_API_URL env var', () => {
vi.stubEnv('BERGET_API_URL', 'https://custom.api.example.com');
const config = getAuthConfig();
expect(config.apiBaseUrl).toBe('https://custom.api.example.com');
expect(config.keycloakUrl).toBe('https://keycloak.berget.ai');
expect(config.keycloakUrl).toBe('https://auth.berget.ai');
vi.unstubAllEnvs();
});

Expand Down
20 changes: 10 additions & 10 deletions src/auth/__tests__/issuer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ describe('getConfiguration', () => {
const authConfig = {
apiBaseUrl: 'https://api.berget.ai',
clientId: 'berget-code',
keycloakUrl: 'https://keycloak.berget.ai',
keycloakUrl: 'https://auth.berget.ai',
realm: 'berget',
};

const result1 = await getConfiguration(authConfig);
expect((result1 as any)._url).toBe('https://keycloak.berget.ai/realms/berget');
expect((result1 as any)._url).toBe('https://auth.berget.ai/realms/berget');
expect(mockDiscoveryCalls).toHaveLength(1);

// Second call should use cache
const result2 = await getConfiguration(authConfig);
expect((result2 as any)._url).toBe('https://keycloak.berget.ai/realms/berget');
expect((result2 as any)._url).toBe('https://auth.berget.ai/realms/berget');
expect(mockDiscoveryCalls).toHaveLength(1); // no additional call
});

it('re-discovers after cache is cleared', async () => {
const authConfig = {
apiBaseUrl: 'https://api.berget.ai',
clientId: 'berget-code',
keycloakUrl: 'https://keycloak.berget.ai',
keycloakUrl: 'https://auth.berget.ai',
realm: 'berget',
};

Expand All @@ -52,34 +52,34 @@ describe('getConfiguration', () => {

const stageConfig = {
...authConfig,
keycloakUrl: 'https://keycloak.stage.berget.ai',
keycloakUrl: 'https://auth.stage.berget.ai',
};

const result = await getConfiguration(stageConfig);
expect((result as any)._url).toBe('https://keycloak.stage.berget.ai/realms/berget');
expect((result as any)._url).toBe('https://auth.stage.berget.ai/realms/berget');
expect(mockDiscoveryCalls).toHaveLength(2);
});

it('does not cross-contaminate cache between different issuers', async () => {
const prodConfig = {
apiBaseUrl: 'https://api.berget.ai',
clientId: 'berget-code',
keycloakUrl: 'https://keycloak.berget.ai',
keycloakUrl: 'https://auth.berget.ai',
realm: 'berget',
};

const stageConfig = {
...prodConfig,
keycloakUrl: 'https://keycloak.stage.berget.ai',
keycloakUrl: 'https://auth.stage.berget.ai',
};

// First call discovers stage
const stageResult = await getConfiguration(stageConfig);
expect((stageResult as any)._url).toBe('https://keycloak.stage.berget.ai/realms/berget');
expect((stageResult as any)._url).toBe('https://auth.stage.berget.ai/realms/berget');

// Second call with prod must NOT return stage config from cache
const prodResult = await getConfiguration(prodConfig);
expect((prodResult as any)._url).toBe('https://keycloak.berget.ai/realms/berget');
expect((prodResult as any)._url).toBe('https://auth.berget.ai/realms/berget');
expect(mockDiscoveryCalls).toHaveLength(2); // two distinct discoveries
});
});
6 changes: 3 additions & 3 deletions src/auth/__tests__/pkce-flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ vi.mock('openid-client', async () => {
return {
authorizationCodeGrant: vi.fn(),
buildAuthorizationUrl: vi.fn((_config, params) => {
const url = new URL('https://keycloak.berget.ai/realms/berget/protocol/openid-connect/auth');
const url = new URL('https://auth.berget.ai/realms/berget/protocol/openid-connect/auth');
for (const [key, value] of Object.entries(params)) {
url.searchParams.set(key, value as string);
}
Expand Down Expand Up @@ -304,7 +304,7 @@ describe('startPkceFlow', () => {

// Keycloak sends extra params like iss and session_state
const req = {
url: '/callback?code=authcode123&state=mock-state-uuid&iss=https%3A%2F%2Fkeycloak.berget.ai%2Frealms%2Fberget&session_state=abc-def',
url: '/callback?code=authcode123&state=mock-state-uuid&iss=https%3A%2F%2Fauth.berget.ai%2Frealms%2Fberget&session_state=abc-def',
};
const res = { end: vi.fn(), writeHead: vi.fn() };
mockServer._triggerRequest(req, res);
Expand All @@ -315,7 +315,7 @@ describe('startPkceFlow', () => {
const passedUrl = (authorizationCodeGrant as ReturnType<typeof vi.fn>).mock.calls[0][1] as URL;
expect(passedUrl.searchParams.get('code')).toBe('authcode123');
expect(passedUrl.searchParams.get('state')).toBe('mock-state-uuid');
expect(passedUrl.searchParams.get('iss')).toBe('https://keycloak.berget.ai/realms/berget');
expect(passedUrl.searchParams.get('iss')).toBe('https://auth.berget.ai/realms/berget');
expect(passedUrl.searchParams.get('session_state')).toBe('abc-def');
});
});
4 changes: 2 additions & 2 deletions src/auth/__tests__/token-refresh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ describe('refreshAccessToken', () => {
const storeB = createMockStore({
_data: { access_token: 'old-b', expires_at: 1, refresh_token: 'refresh-b' },
});
const configA = { issuer: 'https://keycloak.berget.ai' } as any;
const configB = { issuer: 'https://keycloak.stage.berget.ai' } as any;
const configA = { issuer: 'https://auth.berget.ai' } as any;
const configB = { issuer: 'https://auth.stage.berget.ai' } as any;

mockRefreshTokenGrantResult = {
access_token: 'new-token',
Expand Down
10 changes: 5 additions & 5 deletions src/auth/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ export function getAuthConfig(options?: { local?: boolean; stage?: boolean }): A
apiBaseUrl = process.env.BERGET_API_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';

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'.

} else {
keycloakUrl = 'https://keycloak.berget.ai';
keycloakUrl = 'https://auth.berget.ai';
}
} else if (options?.local) {
apiBaseUrl = 'http://localhost:3000';
keycloakUrl = 'https://keycloak.stage.berget.ai';
keycloakUrl = 'https://auth.stage.berget.ai';
} else if (options?.stage) {
apiBaseUrl = 'https://api.stage.berget.ai';
keycloakUrl = 'https://keycloak.stage.berget.ai';
keycloakUrl = 'https://auth.stage.berget.ai';
} 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.

}

return {
Expand Down
Loading