-
Notifications
You must be signed in to change notification settings - Fork 3
feat(journey-client): wellknown-endpoint-config-support #525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b8f8084
7e7e659
871f160
b688a2f
4c6cc8e
16c00e8
6f0ff56
331ea2f
95eee18
8ffc980
8b88793
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| --- | ||
| '@forgerock/journey-client': minor | ||
| '@forgerock/sdk-oidc': minor | ||
| '@forgerock/sdk-utilities': minor | ||
| '@forgerock/davinci-client': patch | ||
| '@forgerock/oidc-client': patch | ||
| --- | ||
|
|
||
| ### @forgerock/journey-client | ||
|
|
||
| Add well-known OIDC endpoint discovery support. The journey client can now fetch configuration from the `.well-known/openid-configuration` endpoint: | ||
|
|
||
| ```typescript | ||
| const client = await journey({ | ||
| serverConfig: { | ||
| baseUrl: 'https://am.example.com/am/', | ||
| wellknown: | ||
| 'https://am.example.com/am/oauth2/realms/root/realms/alpha/.well-known/openid-configuration', | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| The realm path can be automatically inferred from the well-known issuer URL. | ||
|
|
||
| ### @forgerock/sdk-oidc | ||
|
|
||
| Add shared well-known module with RTK Query API for OIDC endpoint discovery: | ||
|
|
||
| - `wellknownApi` - RTK Query API for fetching well-known configuration | ||
| - `createWellknownSelector` - Selector factory for cached well-known data | ||
| - `createWellknownError` - Typed error creation from fetch failures | ||
| - Re-exports pure utilities from `@forgerock/sdk-utilities` | ||
|
|
||
| ### @forgerock/sdk-utilities | ||
|
|
||
| Add pure well-known utilities: | ||
|
|
||
| - `inferRealmFromIssuer` - Extract realm path from AM issuer URLs | ||
| - `isValidWellknownUrl` - Validate well-known URLs (HTTPS required, HTTP allowed for localhost) | ||
|
|
||
| ### @forgerock/davinci-client | ||
|
|
||
| Refactored to use shared well-known module from `@forgerock/sdk-oidc`. | ||
|
|
||
| ### @forgerock/oidc-client | ||
|
|
||
| Refactored to use shared well-known module from `@forgerock/sdk-oidc`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,7 +63,7 @@ async function authorization(req, res, next) { | |
|
|
||
| export default function (app) { | ||
| // Passthrough route that enforces authentication | ||
| app.all('/resource/*', async (req, res, next) => { | ||
| app.all('/resource/{*splat}', async (req, res, next) => { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed when i rebased open-deps (part of this express upgrade) |
||
| if (env.NODE_ENV === 'LIVE' && req.hostname === FORGEOPS) { | ||
| // Only enforce authentication if IG is not used | ||
| // In other words, the call comes directly from app | ||
|
|
@@ -156,7 +156,7 @@ export default function (app) { | |
| } | ||
| }); | ||
|
|
||
| app.get('/resource/rest/*', wait, authorization, async (req, res) => { | ||
| app.get('/resource/rest/{*splat}', wait, authorization, async (req, res) => { | ||
| if (env.NODE_ENV === 'live') { | ||
| if (req.access.actions && req.access.actions.GET) { | ||
| res.json({ message: 'Successfully retrieved resource!' }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,7 @@ | |
| "path": "./node_modules/cz-conventional-changelog" | ||
| } | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": { | ||
| "@changesets/changelog-github": "^0.5.0", | ||
| "@changesets/cli": "^2.27.9", | ||
|
|
@@ -58,17 +59,18 @@ | |
| "@effect/cli": "catalog:effect", | ||
| "@eslint/eslintrc": "^3.0.0", | ||
| "@eslint/js": "~9.39.0", | ||
| "@nx/devkit": "21.2.3", | ||
| "@nx/eslint": "21.2.3", | ||
| "@nx/eslint-plugin": "21.2.3", | ||
| "@nx/express": "21.2.3", | ||
| "@nx/jest": "21.2.3", | ||
| "@nx/js": "21.2.3", | ||
| "@nx/playwright": "21.2.3", | ||
| "@nx/plugin": "21.2.3", | ||
| "@nx/vite": "21.2.3", | ||
| "@nx/web": "21.2.3", | ||
| "@nx/workspace": "21.2.3", | ||
| "@nx/devkit": "22.3.3", | ||
| "@nx/eslint": "22.3.3", | ||
| "@nx/eslint-plugin": "22.3.3", | ||
| "@nx/express": "22.3.3", | ||
| "@nx/jest": "22.3.3", | ||
| "@nx/js": "22.3.3", | ||
| "@nx/playwright": "22.3.3", | ||
| "@nx/plugin": "22.3.3", | ||
| "@nx/vite": "22.3.3", | ||
| "@nx/vitest": "22.3.3", | ||
| "@nx/web": "22.3.3", | ||
| "@nx/workspace": "22.3.3", | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "@playwright/test": "^1.47.2", | ||
| "@swc-node/register": "1.10.10", | ||
| "@swc/cli": "0.6.0", | ||
|
|
@@ -82,8 +84,8 @@ | |
| "@typescript-eslint/parser": "^8.45.0", | ||
| "@typescript-eslint/typescript-estree": "8.23.0", | ||
| "@typescript-eslint/utils": "^8.13.0", | ||
| "@vitest/coverage-v8": "^3.0.5", | ||
| "@vitest/ui": "3.0.4", | ||
| "@vitest/coverage-v8": "4.0.9", | ||
| "@vitest/ui": "4.0.9", | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "conventional-changelog-conventionalcommits": "^8.0.0", | ||
| "cz-conventional-changelog": "^3.3.0", | ||
| "cz-git": "^1.6.1", | ||
|
|
@@ -100,7 +102,7 @@ | |
| "jsonc-eslint-parser": "^2.1.0", | ||
| "lint-staged": "^15.0.0", | ||
| "madge": "8.0.0", | ||
| "nx": "21.2.3", | ||
| "nx": "22.3.3", | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all of this is because of dependency upgrades |
||
| "pkg-pr-new": "^0.0.60", | ||
| "playwright": "^1.47.2", | ||
| "prettier": "^3.2.5", | ||
|
|
@@ -115,9 +117,9 @@ | |
| "typescript": "5.8.3", | ||
| "typescript-eslint": "^8.19.0", | ||
| "verdaccio": "6.2.1", | ||
| "vite": "6.4.1", | ||
| "vite": "catalog:vite", | ||
| "vitest": "catalog:vitest", | ||
| "vitest-canvas-mock": "^0.3.3" | ||
| "vitest-canvas-mock": "catalog:vitest" | ||
| }, | ||
| "packageManager": "pnpm@10.21.0+sha512.da3337267e400fdd3d479a6c68079ac6db01d8ca4f67572083e722775a796788a7a9956613749e000fac20d424b594f7a791a5f4e2e13581c5ef947f26968a40", | ||
| "engines": { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,7 +15,7 @@ import { createClientStore, handleUpdateValidateError, RootState } from './clien | |||||||||||||||||||||||||||||
| import { nodeSlice } from './node.slice.js'; | ||||||||||||||||||||||||||||||
| import { davinciApi } from './davinci.api.js'; | ||||||||||||||||||||||||||||||
| import { configSlice } from './config.slice.js'; | ||||||||||||||||||||||||||||||
| import { wellknownApi } from './wellknown.api.js'; | ||||||||||||||||||||||||||||||
| import { wellknownApi, createWellknownError } from '@forgerock/sdk-oidc'; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import type { ActionTypes, RequestMiddleware } from '@forgerock/sdk-request-middleware'; | ||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
|
|
@@ -88,14 +88,14 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({ | |||||||||||||||||||||||||||||
| throw error; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const { data: openIdResponse } = await store.dispatch( | ||||||||||||||||||||||||||||||
| wellknownApi.endpoints.wellknown.initiate(config.serverConfig.wellknown), | ||||||||||||||||||||||||||||||
| const { data: openIdResponse, error: fetchError } = await store.dispatch( | ||||||||||||||||||||||||||||||
| wellknownApi.endpoints.configuration.initiate(config.serverConfig.wellknown), | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (!openIdResponse) { | ||||||||||||||||||||||||||||||
| const error = new Error('error fetching `wellknown` response for OpenId Configuration'); | ||||||||||||||||||||||||||||||
| log.error(error.message); | ||||||||||||||||||||||||||||||
| throw error; | ||||||||||||||||||||||||||||||
| if (fetchError || !openIdResponse) { | ||||||||||||||||||||||||||||||
| const genericError = createWellknownError(fetchError); | ||||||||||||||||||||||||||||||
| log.error(`${genericError.error}: ${genericError.message}`); | ||||||||||||||||||||||||||||||
| throw new Error(genericError.message); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| store.dispatch(configSlice.actions.set({ ...config, wellknownResponse: openIdResponse })); | ||||||||||||||||||||||||||||||
|
|
@@ -249,11 +249,11 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({ | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| return node; | ||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||
| const error = err as Error; | ||||||||||||||||||||||||||||||
| log.error(error.message); | ||||||||||||||||||||||||||||||
| const errorMessage = err instanceof Error ? err.message : String(err); | ||||||||||||||||||||||||||||||
| log.error(errorMessage); | ||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||
| error: { | ||||||||||||||||||||||||||||||
| message: error.message ?? 'An unexpected error occurred during resume operation', | ||||||||||||||||||||||||||||||
| message: errorMessage || 'An unexpected error occurred during resume operation', | ||||||||||||||||||||||||||||||
| type: 'internal_error', | ||||||||||||||||||||||||||||||
|
Comment on lines
+252
to
257
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid
🔧 Suggested tweak- const errorMessage = err instanceof Error ? err.message : String(err);
- log.error(errorMessage);
+ const errorMessage =
+ err instanceof Error ? err.message : err ? String(err) : '';
+ log.error(errorMessage || 'An unexpected error occurred during resume operation');📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| type: 'internal_error', | ||||||||||||||||||||||||||||||
|
|
@@ -336,10 +336,10 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({ | |||||||||||||||||||||||||||||
| store.dispatch(nodeSlice.actions.update({ id, value, index })); | ||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||
| const error = err as Error; | ||||||||||||||||||||||||||||||
| const errorMessage = err instanceof Error ? err.message : String(err); | ||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||
| type: 'internal_error', | ||||||||||||||||||||||||||||||
| error: { message: error.message, type: 'internal_error' }, | ||||||||||||||||||||||||||||||
| error: { message: errorMessage, type: 'internal_error' }, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.