Skip to content

Commit 8ffc980

Browse files
committed
chore: coderabbit-comments
1 parent 95eee18 commit 8ffc980

6 files changed

Lines changed: 36 additions & 169 deletions

File tree

e2e/am-mock-api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
"uuid": "^13.0.0"
1717
},
1818
"devDependencies": {
19-
"@types/express": "^4.17.17"
19+
"@types/express": "^5.0.0"
2020
}
2121
}

packages/journey-client/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
"@forgerock/sdk-utilities": "workspace:*",
3030
"@forgerock/storage": "workspace:*",
3131
"@reduxjs/toolkit": "catalog:",
32-
"tslib": "^2.3.0",
33-
"vite": "catalog:vite",
34-
"vitest-canvas-mock": "catalog:vitest"
32+
"tslib": "^2.3.0"
3533
},
3634
"devDependencies": {
3735
"@vitest/coverage-v8": "catalog:vitest",

packages/journey-client/src/lib/config.types.ts

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,89 +8,35 @@
88
import type { BaseConfig, WellKnownResponse, PathsConfig } from '@forgerock/sdk-types';
99
import type { RequestMiddleware } from '@forgerock/sdk-request-middleware';
1010

11-
/**
12-
* Standard journey client configuration with explicit baseUrl.
13-
*
14-
* Use this when you want to configure the AM server directly without
15-
* OIDC well-known endpoint discovery.
16-
*
17-
* @example
18-
* ```typescript
19-
* const config: JourneyClientConfig = {
20-
* serverConfig: {
21-
* baseUrl: 'https://am.example.com/am/',
22-
* },
23-
* realmPath: 'alpha',
24-
* };
25-
* ```
26-
*/
11+
export interface JourneyServerConfig {
12+
baseUrl: string;
13+
paths?: PathsConfig['paths'];
14+
timeout?: number;
15+
}
16+
2717
export interface JourneyClientConfig extends BaseConfig {
18+
serverConfig: JourneyServerConfig;
2819
middleware?: Array<RequestMiddleware>;
2920
realmPath?: string;
3021
}
3122

32-
/**
33-
* Server configuration that includes well-known OIDC endpoint discovery.
34-
*
35-
* When wellknown is provided, the client will fetch the OIDC discovery
36-
* document to obtain endpoints like authorization, token, userinfo, etc.
37-
*
38-
* Note: baseUrl is still required for AM-specific endpoints (authenticate,
39-
* sessions) which are not part of the standard OIDC well-known response.
40-
*/
4123
export interface WellknownServerConfig {
42-
/** Base URL for AM-specific endpoints (authenticate, sessions) */
4324
baseUrl: string;
44-
/** URL to the OIDC well-known configuration endpoint */
4525
wellknown: string;
46-
/** Custom path overrides for endpoints */
4726
paths?: PathsConfig['paths'];
48-
/** Request timeout in milliseconds */
4927
timeout?: number;
5028
}
5129

52-
/**
53-
* Journey client configuration with OIDC well-known endpoint discovery.
54-
*
55-
* This configuration fetches the OIDC discovery document to obtain
56-
* standard OIDC endpoints while still using baseUrl for AM-specific
57-
* journey endpoints.
58-
*
59-
* @example
60-
* ```typescript
61-
* const config: AsyncJourneyClientConfig = {
62-
* serverConfig: {
63-
* baseUrl: 'https://am.example.com/am/',
64-
* wellknown: 'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration',
65-
* },
66-
* // realmPath is optional - can be inferred from the well-known issuer
67-
* };
68-
* ```
69-
*/
7030
export interface AsyncJourneyClientConfig {
7131
serverConfig: WellknownServerConfig;
7232
middleware?: Array<RequestMiddleware>;
73-
/** Optional realm path - can be inferred from well-known issuer if not provided */
7433
realmPath?: string;
7534
}
7635

77-
/**
78-
* Internal configuration type that includes the resolved well-known response.
79-
*
80-
* This type is used internally after the well-known endpoint has been fetched
81-
* and the configuration has been normalized.
82-
*/
8336
export interface InternalJourneyClientConfig extends JourneyClientConfig {
84-
/** The fetched OIDC well-known response, if wellknown discovery was used */
8537
wellknownResponse?: WellKnownResponse;
8638
}
8739

88-
/**
89-
* Union type for journey client initialization.
90-
*
91-
* Accepts either a standard configuration with baseUrl only,
92-
* or an async configuration with well-known endpoint discovery.
93-
*/
9440
export type JourneyConfigInput = JourneyClientConfig | AsyncJourneyClientConfig;
9541

9642
export type { RequestMiddleware };

packages/journey-client/src/lib/interfaces.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@
55
* of the MIT license. See the LICENSE file for details.
66
*/
77

8-
import { JourneyClientConfig } from './config.types.js';
98
import { JourneyStep } from './step.types.js';
109

11-
export interface StartParam extends JourneyClientConfig {
10+
export interface StartParam {
1211
journey: string;
1312
query?: Record<string, string>;
1413
}
1514

16-
export interface ResumeOptions extends JourneyClientConfig {
15+
export interface ResumeOptions {
1716
journey?: string;
1817
query?: Record<string, string>;
1918
}
2019

21-
export interface NextOptions extends JourneyClientConfig {
20+
export interface NextOptions {
2221
query?: Record<string, string>;
2322
}
2423

packages/journey-client/src/lib/wellknown.utils.ts

Lines changed: 16 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,101 +5,45 @@
55
* of the MIT license. See the LICENSE file for details.
66
*/
77

8-
// Re-export error handling from sdk-oidc (uses RTK Query types)
98
export { createWellknownError } from '@forgerock/sdk-oidc';
10-
11-
// Re-export URL validation from sdk-utilities (pure utility)
129
export { isValidWellknownUrl } from '@forgerock/sdk-utilities';
1310

1411
import type { AsyncJourneyClientConfig, JourneyConfigInput } from './config.types.js';
1512

13+
const REALM_PATTERNS = [
14+
/\/oauth2\/realms\/root\/realms\/(.+)$/, // Legacy subrealm: /oauth2/realms/root/realms/{realm}
15+
/\/oauth2\/realms\/(root)$/, // Legacy root: /oauth2/realms/root
16+
/\/oauth2\/([^/]+)$/, // Simplified: /oauth2/{realm}
17+
] as const;
18+
1619
/**
17-
* Attempts to infer the realm path from a ForgeRock AM issuer URL.
18-
*
19-
* AM issuer URLs follow one of two patterns:
20-
* - Simplified: `https://{host}/am/oauth2/{realm}` (e.g., `/am/oauth2/alpha`)
21-
* - Legacy: `https://{host}/am/oauth2/realms/root/realms/{realm}`
22-
*
23-
* This function extracts the realm from either format.
24-
* Returns undefined for non-AM issuers (e.g., PingOne, generic OIDC).
25-
*
26-
* @param issuer - The issuer URL from the well-known response
27-
* @returns The inferred realm path, or undefined if it cannot be determined
28-
*
29-
* @example
30-
* ```typescript
31-
* // Simplified format (common in ForgeBlocks)
32-
* inferRealmFromIssuer('https://openam-sdks.forgeblocks.com/am/oauth2/alpha')
33-
* // Returns: 'alpha'
34-
*
35-
* // Legacy format with explicit realm path
36-
* inferRealmFromIssuer('https://am.example.com/am/oauth2/realms/root/realms/alpha')
37-
* // Returns: 'alpha'
38-
*
39-
* // Nested subrealm (legacy format)
40-
* inferRealmFromIssuer('https://am.example.com/am/oauth2/realms/root/realms/customers/realms/premium')
41-
* // Returns: 'customers/realms/premium'
42-
*
43-
* // Non-AM issuer (e.g., PingOne)
44-
* inferRealmFromIssuer('https://auth.pingone.com/env-id/as')
45-
* // Returns: undefined
46-
* ```
20+
* Infers the realm path from a ForgeRock AM issuer URL.
21+
* Returns undefined for non-AM issuers.
4722
*/
4823
export function inferRealmFromIssuer(issuer: string): string | undefined {
4924
try {
50-
const url = new URL(issuer);
51-
const pathname = url.pathname;
52-
53-
// Pattern 1: Legacy subrealm - /oauth2/realms/root/realms/{subrealm}
54-
const legacySubRealmMatch = pathname.match(/\/oauth2\/realms\/root\/realms\/(.+)$/);
55-
if (legacySubRealmMatch) {
56-
return legacySubRealmMatch[1];
57-
}
58-
59-
// Pattern 2: Legacy root realm - /oauth2/realms/root
60-
const legacyRootMatch = pathname.match(/\/oauth2\/realms\/(root)$/);
61-
if (legacyRootMatch) {
62-
return legacyRootMatch[1];
63-
}
64-
65-
// Pattern 3: Simplified format - /oauth2/{realm} (e.g., /am/oauth2/alpha)
66-
const simplifiedMatch = pathname.match(/\/oauth2\/([^/]+)$/);
67-
if (simplifiedMatch) {
68-
return simplifiedMatch[1];
25+
const pathname = new URL(issuer).pathname;
26+
for (const pattern of REALM_PATTERNS) {
27+
const match = pathname.match(pattern);
28+
if (match) return match[1];
6929
}
70-
7130
return undefined;
7231
} catch {
7332
return undefined;
7433
}
7534
}
7635

7736
/**
78-
* Type guard to determine if the configuration includes well-known endpoint discovery.
79-
*
80-
* @param config - The journey client configuration (union of sync and async configs)
81-
* @returns True if the config has a wellknown property in serverConfig
82-
*
83-
* @example
84-
* ```typescript
85-
* const config: JourneyConfigInput = {
86-
* serverConfig: {
87-
* baseUrl: 'https://am.example.com/am/',
88-
* wellknown: 'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration'
89-
* }
90-
* };
91-
*
92-
* if (hasWellknownConfig(config)) {
93-
* // TypeScript now knows config is AsyncJourneyClientConfig
94-
* const wellknownUrl = config.serverConfig.wellknown;
95-
* }
96-
* ```
37+
* Type guard to check if config uses well-known endpoint discovery.
9738
*/
9839
export function hasWellknownConfig(config: JourneyConfigInput): config is AsyncJourneyClientConfig {
9940
return (
10041
'serverConfig' in config &&
10142
typeof config.serverConfig === 'object' &&
10243
config.serverConfig !== null &&
44+
'baseUrl' in config.serverConfig &&
45+
typeof config.serverConfig.baseUrl === 'string' &&
46+
config.serverConfig.baseUrl.length > 0 &&
10347
'wellknown' in config.serverConfig &&
10448
typeof config.serverConfig.wellknown === 'string' &&
10549
config.serverConfig.wellknown.length > 0

pnpm-lock.yaml

Lines changed: 8 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)