Skip to content

OpenAM UI JS SDK #941

Draft
maximthomas wants to merge 39 commits intoOpenIdentityPlatform:masterfrom
maximthomas:openam-js-sdk
Draft

OpenAM UI JS SDK #941
maximthomas wants to merge 39 commits intoOpenIdentityPlatform:masterfrom
maximthomas:openam-js-sdk

Conversation

@maximthomas
Copy link
Copy Markdown
Contributor

Experimental UI based on React JS library.
Allows to develop a custom OpenAM UI using pluggable components, see the README.md file

@maximthomas maximthomas requested a review from vharseko November 26, 2025 10:05
@maximthomas maximthomas added the javascript Pull requests that update Javascript code label Nov 26, 2025
@vharseko vharseko changed the title OpenAM UI JS SDK initial commit OpenAM UI JS SDK Nov 26, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an experimental React/Vite-based “OpenAM UI JS SDK” module to the OpenAM UI build, packages it as distributable ZIP artifacts (app + library), and wires the app bundle into the openam-server-only WAR under extui/ (with a small CORS schema update to allow Accept-API-Version).

Changes:

  • Introduce new openam-ui-js-sdk Maven module with Vite/Vitest/TypeScript project (app + library builds, plus assemblies).
  • Package and embed the generated app ZIP into openam-server-only WAR under extui/.
  • Bump frontend build toolchain versions (frontend-maven-plugin, Node, npm) and update CORS allowed headers.

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 23 comments.

Show a summary per file
File Description
pom.xml Adds openam-ui-js-sdk app ZIP as a dependency in the root build.
openam-ui/pom.xml Registers new UI module and bumps frontend-maven-plugin/Node/npm versions.
openam-ui/openam-ui-js-sdk/vitest.config.js Vitest configuration (jsdom + setup file).
openam-ui/openam-ui-js-sdk/vite.lib.config.ts Vite config for library build + DTS generation.
openam-ui/openam-ui-js-sdk/vite.config.ts Vite config for app build output to target/app.
openam-ui/openam-ui-js-sdk/tsconfig.node.json TS config for Vite config files.
openam-ui/openam-ui-js-sdk/tsconfig.lib.json TS config for library build typings/source scope.
openam-ui/openam-ui-js-sdk/tsconfig.json Project references for TS build mode.
openam-ui/openam-ui-js-sdk/tsconfig.app.json TS config for app compilation scope.
openam-ui/openam-ui-js-sdk/src/main.tsx App entry point rendering OpenAMUI.
openam-ui/openam-ui-js-sdk/src/lib/userService.ts Client-side calls for user/session/profile/password operations.
openam-ui/openam-ui-js-sdk/src/lib/types.ts SDK response/data type definitions.
openam-ui/openam-ui-js-sdk/src/lib/setupTests.ts Test environment setup for RTL matchers.
openam-ui/openam-ui-js-sdk/src/lib/router.tsx Hash router definition + service instantiation.
openam-ui/openam-ui-js-sdk/src/lib/loginService.ts Client-side authentication request/callback submission helpers.
openam-ui/openam-ui-js-sdk/src/lib/index.ts Library public exports (components + config/types).
openam-ui/openam-ui-js-sdk/src/lib/env.d.ts Vite env typings for OpenAM URL configuration variables.
openam-ui/openam-ui-js-sdk/src/lib/config.ts Global mutable config + default component implementations.
openam-ui/openam-ui-js-sdk/src/lib/components/types.ts Pluggable UI component type contracts.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultUserForm.tsx Default user profile + change password modal UI.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultUserForm.test.tsx Tests for default user form behavior.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultLoginForm.tsx Default login form rendering callbacks + actions.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultLoginForm.test.tsx Tests for default login form integration with config.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultErrorForm.tsx Default error UI component.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultErrorForm.test.tsx Tests for default error UI.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultCallbackElement.tsx Default rendering for OpenAM callback types.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultCallbackElement.test.tsx Tests for callback element rendering/value updates.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultActionElements.tsx Default submit/action button rendering for callbacks.
openam-ui/openam-ui-js-sdk/src/lib/components/DefaultActionElements.test.tsx Tests for action element behavior.
openam-ui/openam-ui-js-sdk/src/lib/__tests__/mocks.ts Mock auth/user payloads for component tests.
openam-ui/openam-ui-js-sdk/src/lib/User.tsx User route: session check, profile load/save, password update.
openam-ui/openam-ui-js-sdk/src/lib/OpenAMUI.tsx SDK root component mounting the router provider.
openam-ui/openam-ui-js-sdk/src/lib/NotFoundPage.tsx 404 page component.
openam-ui/openam-ui-js-sdk/src/lib/Login.tsx Login route: init, submit callbacks, redirect or route change.
openam-ui/openam-ui-js-sdk/src/lib/Home.tsx Home route: redirect to login or user based on session.
openam-ui/openam-ui-js-sdk/src/index.scss Basic styling for forms/modals.
openam-ui/openam-ui-js-sdk/pom.xml Maven build for npm test/build + assembly ZIPs (app + lib).
openam-ui/openam-ui-js-sdk/package.json React/React Router/Vite/Vitest/TS toolchain definitions and scripts.
openam-ui/openam-ui-js-sdk/index.html Vite HTML entry document.
openam-ui/openam-ui-js-sdk/eslint.config.js ESLint config for TS/React hooks/refresh.
openam-ui/openam-ui-js-sdk/assembly/lib-zip.xml Assembly descriptor for library ZIP artifact.
openam-ui/openam-ui-js-sdk/assembly/app-zip.xml Assembly descriptor for app ZIP artifact.
openam-ui/openam-ui-js-sdk/README.md Usage/customization docs for app and SDK consumption.
openam-ui/openam-ui-js-sdk/.gitignore Ignores for node/vite outputs and zips.
openam-ui/openam-ui-js-sdk/.env.development Dev env defaults for OpenAM server/context path.
openam-ui/openam-ui-js-sdk/.env Sample env variables (commented).
openam-server-only/src/main/resources/services/amCORS.xml Allows Accept-API-Version header; bumps revisionNumber.
openam-server-only/pom.xml Downloads app ZIP, stages under extui/, and includes it in WAR resources; adds ZIP dependency.
.github/workflows/deploy.yml Excludes openam-ui-js-sdk from javadoc aggregate build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +3
import type { ErrorForm } from "./types";

const DefaultErrorForm: ErrorForm = ({ error, resetError }) => {
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This file is missing the standard CDDL header block that is present in the other new JS SDK source files. Please add the project’s license header here as well for consistency/compliance.

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +74
const response = await fetch(userUrl, {
method: "GET",
mode: "cors",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
})
return await response.json();
} catch (e) {
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

getUserData returns response.json() without checking response.ok. For non-2xx responses, this can silently propagate error payloads as UserData and break callers. Handle non-OK responses (e.g., parse an error shape and throw) before returning data.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +108
const response = await fetch(userUrl, {
method: "PUT",
mode: "cors",
credentials: "include",
headers: {
"Accept-API-Version": "resource=2.0, protocol=1.0",
"Content-Type": "application/json"
},
body: JSON.stringify(dataToUpdate),
}
)
return await response.json();
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

saveUserData returns response.json() even when the server responds with a non-2xx status. This can make the UI treat error payloads as successful updates. Add a response.ok check and surface a useful error (similar to savePassword).

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +99
import { setConfig } from 'openam-js-sdk'

setConfig({
openamServer: 'https://openam.example.org:443',
openamContextPath: '/am',
errorForm: ({ error, resetError }) => {
return <div>
<h1>An error occurred</h1>
<p>{error?.message}</p>
<input type="button" value="Retry" onClick={() => resetError()} />
</div>
})

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The customization example uses errorForm, but the config interface property is ErrorForm (capital E) and the default config also uses ErrorForm. As written, the example won’t override the error UI. Update the README example to match the actual config API shape.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
setConfig({
CallbackElement: mockCallbackElement,
ActionElements: mockActionElements,
})

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This test mutates the global singleton config via setConfig at module initialization time, which can leak state into other test files depending on execution order. Prefer setting config in beforeEach/beforeAll and restoring the previous config in afterEach/afterAll to keep tests isolated.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +30
const config = getConfig();
const userService = new UserService(config.getOpenAmUrl());
const loginService = new LoginService(config.getOpenAmUrl());

const router = createHashRouter([
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

config, userService, loginService, and the router are instantiated at module load time. Since consumers are expected to call setConfig(...) to customize openamServer/openamContextPath, importing OpenAMUI (via src/lib/index.ts) will run this file before setConfig is called, so the services/router can be locked to the default URL. Consider creating the router/services lazily (e.g., factory function or inside OpenAMUI with useMemo) so updates via setConfig take effect.

Copilot uses AI. Check for mistakes.
maximthomas and others added 18 commits March 30, 2026 10:25
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tyPlatform#943)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…andler.codec.http.HttpRequestEncoder (OpenIdentityPlatform#949)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…DoS via memory exhaustion (OpenIdentityPlatform#950)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…et` and `_.omit` functions (OpenIdentityPlatform#953)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…o prototype pollution in the _.unset and _.omit functions. (OpenIdentityPlatform#954)
…er test in build.yml (OpenIdentityPlatform#959)

Co-authored-by: Valery Kharseko <vharseko@3a-systems.ru>
Open Identity Platform Community and others added 16 commits March 30, 2026 10:30
…f service (OpenIdentityPlatform#960)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…on DoS in parse() + Prototype Pollution via parse() in NodeJS flatted (OpenIdentityPlatform#966)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…asses causes incorrect glob matching Related glob security issue patched in the same release (OpenIdentityPlatform#970)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: vharseko <6818498+vharseko@users.noreply.github.com>
…oted-String Parsing (OpenIdentityPlatform#972)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 48 out of 50 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to +56
console.log("request error ocurred:", e)
}
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

Typo in log message: "request error ocurred" should be "request error occurred".

Copilot uses AI. Check for mistakes.

```tsx
import React from 'react';
import OpenAMUI from 'openam-js-sdk';
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

The README uses a default import (import OpenAMUI from 'openam-js-sdk'), but the library entrypoint exports OpenAMUI as a named export. Update the example to use import { OpenAMUI } ... (or add a default export if that’s the intended API).

Suggested change
import OpenAMUI from 'openam-js-sdk';
import { OpenAMUI } from 'openam-js-sdk';

Copilot uses AI. Check for mistakes.

const renderTextOutputCallback = (callback: Callback) => {
const propMap = Object.fromEntries(callback.output.map((o) => [o.name, o.value]))
const messageType = propMap['messageType']
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

messageType is read from callback.output and can be a number (per CallbackOutput.value). The switch compares it to string literals ("0", "1", ...), so numeric values (0/1/2/4) will fall into the default branch. Normalize messageType (e.g., String(messageType)) or add numeric cases.

Suggested change
const messageType = propMap['messageType']
const messageType = String(propMap["messageType"] ?? "");

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +23
const ScriptElement = (scriptText: string) => {
useEffect(() => {
const script = document.createElement('script');
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

ScriptElement calls useEffect but is invoked as a plain function later (return ScriptElement(message)), not rendered as a React component/custom hook. This violates the Rules of Hooks and can trigger an “Invalid hook call” at runtime. Refactor it into a real component (e.g., <ScriptElement scriptText={...} />) or a custom hook used by a component.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants