This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new a024780b853 NO-ISSUE: Add support for more OIDC parameters in the
Management Console (#2961)
a024780b853 is described below
commit a024780b8536f665738a0daf99838979a44cd1a1
Author: Thiago Lugli <[email protected]>
AuthorDate: Thu Mar 6 14:53:36 2025 -0300
NO-ISSUE: Add support for more OIDC parameters in the Management Console
(#2961)
---
.../README.md | 9 ++-
.../src/main/resources/application.properties | 3 -
.../package.json | 3 +-
.../src/authSessions/AuthSessionApi.ts | 6 +-
.../src/authSessions/AuthSessionMigrations.ts | 4 ++
.../src/authSessions/AuthSessionsContext.tsx | 54 +++++++-------
.../src/authSessions/AuthSessionsService.ts | 31 +++++---
.../authSessions/components/AuthSessionsList.tsx | 12 +++-
.../components/NewAuthSessionLoginSuccessPage.tsx | 52 +++++++++++---
.../components/NewAuthSessionModal.tsx | 84 +++++++++++++++++++---
.../src/runtime/RuntimeContext.tsx | 4 +-
pnpm-lock.yaml | 36 ++++------
12 files changed, 206 insertions(+), 92 deletions(-)
diff --git a/packages/runtime-tools-management-console-webapp/README.md
b/packages/runtime-tools-management-console-webapp/README.md
index 81844d1b61c..ffd5c64e442 100644
--- a/packages/runtime-tools-management-console-webapp/README.md
+++ b/packages/runtime-tools-management-console-webapp/README.md
@@ -85,7 +85,14 @@ To do so, click on the `+ Connect to a runtime…` button and
fill in the requir
modal:
- **Alias**: The name to give your connected runtime instance (can be anything
that helps you identify it).
-- **URL**: The runtime root URL (E.g., http://localhost:8080)
+- **URL**: The runtime root URL (E.g., http://localhost:8080).
+- **Force login prompt**: Check this if you are already logged in your
Identity Provider but would like to log in again (maybe with a different user).
+
+More settings are available in the **Advanced OpenID Connect settings**
section:
+
+- **Client ID**: Overrides the Client ID used for this connection. Defaults to
the value of the `RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID`
environment variable.
+- **Scope**: Overrides the scopes requested to the Identity Provider. Useful
from some Identity Providers that will only grant a Refresh Token if the
`offline_access` scope is included. Defaults to `openid email profile`.
+- **Audience**: This is the `audience` parameter in the Authorization request.
Used to identify the service that the token is intended for. Empty by default.
If your runtime uses OpenID Connect authentication, you should be redirected
to the Identity Provider
(IdP) login page or, if you’re already logged in, redirected back to the
Management Console. If your
diff --git
a/packages/runtime-tools-management-console-webapp/dev-webapp/secured-runtime/src/main/resources/application.properties
b/packages/runtime-tools-management-console-webapp/dev-webapp/secured-runtime/src/main/resources/application.properties
index 1380947ede2..622523d8221 100644
---
a/packages/runtime-tools-management-console-webapp/dev-webapp/secured-runtime/src/main/resources/application.properties
+++
b/packages/runtime-tools-management-console-webapp/dev-webapp/secured-runtime/src/main/resources/application.properties
@@ -45,9 +45,6 @@
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.http.auth.permission.public.paths=/q/*,/docs/*
quarkus.http.auth.permission.public.policy=permit
-# Quarkus OIDC Proxy
-quarkus.oidc-proxy.external-client-id=management-console-dev-webapp
-
quarkus.http.cors=true
quarkus.http.cors.origins=*
diff --git a/packages/runtime-tools-management-console-webapp/package.json
b/packages/runtime-tools-management-console-webapp/package.json
index 8cf626844a3..55aa40e9c46 100644
--- a/packages/runtime-tools-management-console-webapp/package.json
+++ b/packages/runtime-tools-management-console-webapp/package.json
@@ -47,8 +47,7 @@
"axios": "^1.7.4",
"graphql": "14.3.1",
"history": "^4.9.0",
- "oidc-client-ts": "^3.1.0",
- "openid-client": "^6.1.3",
+ "openid-client": "^6.3.3",
"react": "^17.0.2",
"react-apollo": "3.1.3",
"react-apollo-hooks": "^0.5.0",
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionApi.ts
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionApi.ts
index db868cf2c6f..2884343301c 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionApi.ts
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionApi.ts
@@ -27,12 +27,13 @@ export const authSessionBroadcastChannel = new
BroadcastChannel("auth_sessions")
export const AUTH_SESSIONS_FILE_PATH = "/authSessions.json";
export const AUTH_SESSIONS_FS_NAME = "auth_sessions";
-export const AUTH_SESSIONS_VERSION_NUMBER = 1;
+export const AUTH_SESSIONS_VERSION_NUMBER = 2;
export const AUTH_SESSIONS_FS_NAME_WITH_VERSION =
`${AUTH_SESSIONS_FS_NAME}_v${AUTH_SESSIONS_VERSION_NUMBER.toString()}`;
export const AUTH_SESSION_TEMP_OPENID_AUTH_DATA_STORAGE_KEY =
"temporaryOpenIdAuthData";
export const AUTH_SESSION_RUNTIME_AUTH_SERVER_URL_ENDPOINT = "q/oidc";
export const AUTH_SESSION_RUNTIME_AUTH_SERVER_OPENID_CONFIGURATION_PATH =
".well-known/openid-configuration";
+export const AUTH_SESSION_OIDC_DEFAULT_SCOPES = "openid email profile";
export function mapSerializer(_: string, value: any) {
if (value instanceof Map) {
@@ -90,6 +91,8 @@ export type OpenIDConnectAuthSession = {
userInfo: UserInfoResponse;
clientId: string;
clientSecret?: string;
+ audience?: string;
+ scope: string;
runtimeUrl: string;
status: AuthSessionStatus;
createdAtDateISO: string;
@@ -118,6 +121,7 @@ export type OidcAuthUrlParameters = {
nonce?: string;
prompt?: string;
state?: string;
+ audience?: string;
};
export type TemporaryAuthSessionData =
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionMigrations.ts
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionMigrations.ts
index d8fcf560c9d..b355310edb8 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionMigrations.ts
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionMigrations.ts
@@ -19,6 +19,7 @@
import { decoder } from
"@kie-tools-core/workspaces-git-fs/dist/encoderdecoder/EncoderDecoder";
import {
+ AUTH_SESSION_OIDC_DEFAULT_SCOPES,
AUTH_SESSIONS_FILE_PATH,
AUTH_SESSIONS_FS_NAME,
AUTH_SESSIONS_VERSION_NUMBER,
@@ -92,6 +93,9 @@ export async function applyAuthSessionMigrations(authSession:
any): Promise<Auth
switch (authSession.version) {
case undefined:
case 1:
+ newAuthSession.version = 2;
+ newAuthSession.scope = AUTH_SESSION_OIDC_DEFAULT_SCOPES;
+ case 2:
// Already at current version. Nothing to do.
default:
break;
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsContext.tsx
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsContext.tsx
index 9547a8657ea..f4f7c84830f 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsContext.tsx
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsContext.tsx
@@ -36,7 +36,6 @@ import {
} from "./AuthSessionApi";
import { deleteOlderAuthSessionsStorage, migrateAuthSessions } from
"./AuthSessionMigrations";
import { AuthSessionsService } from "./AuthSessionsService";
-import { useEnv } from "../env/hooks/EnvContext";
export type AuthSessionsContextType = {
authSessions: Map<string, AuthSession>;
@@ -74,7 +73,6 @@ export function AuthSessionsContextProvider(props:
PropsWithChildren<{}>) {
const [isAuthSessionsReady, setIsAuthSessionsReady] =
useState<boolean>(false);
const [currentAuthSession, setCurrentAuthSession] = useState<AuthSession>();
const [onSelectAuthSession, setOnSelectAuthSession] = useState<(authSession:
AuthSession) => void>();
- const { env } = useEnv();
const getAuthSessionsFromFile = useCallback(async () => {
const fs =
authSessionFsCache.getOrCreateFs(AUTH_SESSIONS_FS_NAME_WITH_VERSION);
@@ -153,36 +151,32 @@ export function AuthSessionsContextProvider(props:
PropsWithChildren<{}>) {
authSessionBroadcastChannel.onmessage = refresh;
}, [refresh]);
- const reauthSessionsAndCalculateStatus = useCallback(
- async (authSessions: Map<string, AuthSession>) => {
- const updatedSessions = await Promise.all(
- [...(authSessions?.values() ?? [])].map(async (authSession) => {
- try {
- if (isOpenIdConnectAuthSession(authSession)) {
- const newAuthSessionData = await
AuthSessionsService.reauthenticate({
- authSession,
- clientId:
env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
- });
- return {
- ...authSession,
- ...newAuthSessionData,
- };
- } else {
- return {
- ...authSession,
- status: AuthSessionStatus.VALID,
- };
- }
- } catch (e) {
- return { ...authSession, status: AuthSessionStatus.INVALID };
+ const reauthSessionsAndCalculateStatus = useCallback(async (authSessions:
Map<string, AuthSession>) => {
+ const updatedSessions = await Promise.all(
+ [...(authSessions?.values() ?? [])].map(async (authSession) => {
+ try {
+ if (isOpenIdConnectAuthSession(authSession)) {
+ const newAuthSessionData = await
AuthSessionsService.reauthenticate({
+ authSession,
+ });
+ return {
+ ...authSession,
+ ...newAuthSessionData,
+ };
+ } else {
+ return {
+ ...authSession,
+ status: AuthSessionStatus.VALID,
+ };
}
- })
- );
+ } catch (e) {
+ return { ...authSession, status: AuthSessionStatus.INVALID };
+ }
+ })
+ );
- return new Map(updatedSessions.map((authSession) => [authSession.id,
authSession]));
- },
- [env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID]
- );
+ return new Map(updatedSessions.map((authSession) => [authSession.id,
authSession]));
+ }, []);
// Init
useCancelableEffect(
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsService.ts
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsService.ts
index f1884a499cd..dc17a9719c9 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsService.ts
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/AuthSessionsService.ts
@@ -53,6 +53,8 @@ export class AuthSessionsService {
config: client.Configuration;
loginSuccessRoute: string;
forceLoginPrompt?: boolean;
+ scope: string;
+ audience?: string;
}) {
const code_challenge_method = "S256";
/**
@@ -69,11 +71,12 @@ export class AuthSessionsService {
// redirect user to as.authorization_endpoint
const parameters: OidcAuthUrlParameters = {
redirect_uri: args.loginSuccessRoute,
- scope: "openid email",
+ scope: args.scope,
code_verifier,
code_challenge,
code_challenge_method,
state: uuid(),
+ ...(args.audience ? { audience: args.audience } : {}),
...(args.forceLoginPrompt ? { prompt: "login" } : {}),
};
@@ -164,6 +167,8 @@ export class AuthSessionsService {
authServerUrl: string;
clientId: string;
name: string;
+ scope: string;
+ audience?: string;
forceLoginPrompt?: boolean;
loginSuccessRoute: string;
}) {
@@ -173,6 +178,8 @@ export class AuthSessionsService {
config,
loginSuccessRoute: args.loginSuccessRoute,
forceLoginPrompt: args.forceLoginPrompt,
+ scope: args.scope,
+ audience: args.audience,
});
await AuthSessionsService.redirectToIdentityProviderLogin({ ...args,
config, parameters });
@@ -188,10 +195,6 @@ export class AuthSessionsService {
clientId: args.clientId,
});
- if (!args.authSession.tokens.refresh_token) {
- throw new Error(`No refresh_token found for AuthSession
${args.authSession.id}!`);
- }
-
const endSessionUrl = client.buildEndSessionUrl(config, {
post_logout_redirect_uri: window.location.href,
id_token_hint: args.authSession.tokens.id_token!,
@@ -200,14 +203,18 @@ export class AuthSessionsService {
window.location.href = endSessionUrl.toString();
}
- static async reauthenticate(args: { authSession: OpenIDConnectAuthSession;
clientId: string }) {
+ static async reauthenticate(args: { authSession: OpenIDConnectAuthSession;
fromUnauthorizedRequest?: boolean }) {
const config = await AuthSessionsService.getIdentityProviderConfig({
authServerUrl: args.authSession.issuer,
- clientId: args.clientId,
+ clientId: args.authSession.clientId,
});
if (!args.authSession.tokens.refresh_token) {
- throw new Error(`No refresh_token found for AuthSession
${args.authSession.id}!`);
+ console.log(`No refresh_token found for AuthSession
${args.authSession.id}. Using old token!`);
+ // If reauthentication request came from a 401 Unauthorized response,
force INVALID status.
+ return {
+ status: args.fromUnauthorizedRequest ? AuthSessionStatus.INVALID :
AuthSessionStatus.VALID,
+ };
}
const tokens = await client.refreshTokenGrant(config,
args.authSession.tokens.refresh_token);
@@ -216,6 +223,7 @@ export class AuthSessionsService {
const claims = tokens.claims();
if (!claims) {
// expires_in was not returned by the authorization server
+ console.error(`Failed to extract claims from token for AuthSession:
${args.authSession.id}!`);
throw new Error("Failed to extract claims from token.");
}
const { sub } = claims;
@@ -275,6 +283,7 @@ export class AuthSessionsService {
const claims = tokens.claims();
if (!claims) {
// expires_in was not returned by the authorization server
+ console.error("Failed to extract claims from token");
throw new Error("Failed to extract claims from token.");
}
const { sub } = claims;
@@ -285,12 +294,14 @@ export class AuthSessionsService {
type: AuthSessionType.OPENID_CONNECT,
version: AUTH_SESSIONS_VERSION_NUMBER,
name: temporaryAuthSessionData.name,
- username: userInfo.preferred_username,
- // TODO: This changes between IdPs. Figure out how a generic way to list
the users roles.
+ username: userInfo.preferred_username ?? userInfo.email ?? userInfo.sub,
+ // TODO: This changes between IdPs. Figure out a generic way to list the
users roles.
roles: [],
// TODO: Somehow get this information from the Kogito application.
impersonator: true,
clientId: temporaryAuthSessionData.clientId,
+ audience: temporaryAuthSessionData.parameters.audience,
+ scope: temporaryAuthSessionData.parameters.scope,
tokens,
claims,
runtimeUrl: temporaryAuthSessionData.runtimeUrl,
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/AuthSessionsList.tsx
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/AuthSessionsList.tsx
index d763b19220e..cba757184b2 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/AuthSessionsList.tsx
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/AuthSessionsList.tsx
@@ -161,9 +161,15 @@ export function AuthSessionDescriptionList(props: {
authSession: AuthSession })
<DescriptionListGroup>
<DescriptionListTerm>Refresh Token:</DescriptionListTerm>
<DescriptionListDescription>
- {obfuscate(props.authSession.tokens.refresh_token ?? "")}
-
- <small>{`(...plus ${(props.authSession.tokens.refresh_token
?? "").length - 16} hidden characters)`}</small>
+ {props.authSession.tokens.refresh_token ? (
+ <>
+ {obfuscate(props.authSession.tokens.refresh_token ?? "")}
+
+ <small>{`(...plus
${(props.authSession.tokens.refresh_token ?? "").length - 16} hidden
characters)`}</small>
+ </>
+ ) : (
+ "Not available. Manual reauthentication required once the
access_token expires."
+ )}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionLoginSuccessPage.tsx
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionLoginSuccessPage.tsx
index 7d3a336b77a..707d484c2ef 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionLoginSuccessPage.tsx
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionLoginSuccessPage.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useEffect, useRef } from "react";
+import React, { useEffect, useRef, useState } from "react";
import { useAuthSessions, useAuthSessionsDispatch } from
"../AuthSessionsContext";
import { useHistory } from "react-router";
import { AuthSessionsService } from "../AuthSessionsService";
@@ -26,6 +26,14 @@ import { useRoutes } from "../../navigation/Hooks";
import { AuthSession } from "../AuthSessionApi";
import { PageSection } from "@patternfly/react-core/dist/js/components/Page";
import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import {
+ EmptyState,
+ EmptyStateBody,
+ EmptyStateSecondaryActions,
+ EmptyStateVariant,
+} from "@patternfly/react-core/dist/js/components/EmptyState";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
type Props = {
onAddAuthSession?: (authSession: AuthSession) => void;
@@ -36,6 +44,7 @@ export const NewAuthSessionLoginSuccessPage: React.FC<Props>
= ({ onAddAuthSessi
const { isAuthSessionsReady } = useAuthSessions();
const history = useHistory();
const routes = useRoutes();
+ const [error, setError] = useState(false);
// Since Code Grants can only be used once we want to make sure that the
// addAuthSession function in the useEffect is only called once.
@@ -47,13 +56,19 @@ export const NewAuthSessionLoginSuccessPage:
React.FC<Props> = ({ onAddAuthSessi
}
const addAuthSession = async () => {
isGettingTokens.current = true;
- const authSession = await
AuthSessionsService.buildAuthSession(AuthSessionsService.getTemporaryAuthSessionData());
- await add(authSession);
- AuthSessionsService.cleanTemporaryAuthSessionData();
- if (onAddAuthSession) {
- onAddAuthSession(authSession);
- } else {
- history.push(routes.home.path({}));
+ try {
+ const authSession = await AuthSessionsService.buildAuthSession(
+ AuthSessionsService.getTemporaryAuthSessionData()
+ );
+ await add(authSession);
+ AuthSessionsService.cleanTemporaryAuthSessionData();
+ if (onAddAuthSession) {
+ onAddAuthSession(authSession);
+ } else {
+ history.push(routes.home.path({}));
+ }
+ } catch (e) {
+ setError(true);
}
};
@@ -64,8 +79,25 @@ export const NewAuthSessionLoginSuccessPage: React.FC<Props>
= ({ onAddAuthSessi
<ManagementConsolePageLayout>
<PageSection>
<Bullseye>
- <h2>Login success!</h2>
- <h3>Redirecting...</h3>
+ <EmptyState variant={EmptyStateVariant.large}>
+ <br />
+ <br />
+ <EmptyStateBody>
+ {error ? (
+ <>
+ <p>Failed to get a token from the Identity Provider.</p>
+ <p>Check your settings and try again!</p>
+ </>
+ ) : (
+ <p>Login success! Redirecting...</p>
+ )}
+ </EmptyStateBody>
+ {error && (
+ <EmptyStateSecondaryActions>
+ <Button onClick={() =>
history.push(routes.home.path({}))}>OK</Button>
+ </EmptyStateSecondaryActions>
+ )}
+ </EmptyState>
</Bullseye>
</PageSection>
</ManagementConsolePageLayout>
diff --git
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionModal.tsx
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionModal.tsx
index 9836f5dcdea..4f43199f84d 100644
---
a/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionModal.tsx
+++
b/packages/runtime-tools-management-console-webapp/src/authSessions/components/NewAuthSessionModal.tsx
@@ -17,17 +17,18 @@
* under the License.
*/
-import React, { useCallback, useState } from "react";
+import React, { useCallback, useEffect, useState } from "react";
import { Modal, ModalVariant } from
"@patternfly/react-core/dist/js/components/Modal";
import { Button, ButtonType, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
import { useAuthSessions, useAuthSessionsDispatch } from
"../AuthSessionsContext";
import { AuthSessionsService } from "../AuthSessionsService";
import { useEnv } from "../../env/hooks/EnvContext";
import { useRoutes } from "../../navigation/Hooks";
-import { AuthSession } from "../AuthSessionApi";
+import { AUTH_SESSION_OIDC_DEFAULT_SCOPES, AuthSession } from
"../AuthSessionApi";
import { TextInput } from
"@patternfly/react-core/dist/js/components/TextInput";
import { Form, FormGroup, ActionGroup } from
"@patternfly/react-core/dist/js/components/Form";
import { Checkbox } from "@patternfly/react-core/dist/js/components/Checkbox";
+import { ExpandableSection } from
"@patternfly/react-core/dist/js/components/ExpandableSection";
type Props = {
onAddAuthSession: (authSession: AuthSession) => void;
@@ -40,16 +41,24 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
const routes = useRoutes();
const { env } = useEnv();
+ const [audience, setAudience] = useState<string>();
+ const [scope, setScope] = useState<string>(AUTH_SESSION_OIDC_DEFAULT_SCOPES);
+ const [clientId, setClientId] =
useState<string>(env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID);
+
const { isNewAuthSessionModalOpen } = useAuthSessions();
const { setIsNewAuthSessionModalOpen, add } = useAuthSessionsDispatch();
const [error, setError] = useState<string | null>(null);
const [isLoading, setLoading] = useState(false);
+ const [isAdvancedOIDCSettingsExpanded, setIsAdvancedOIDCSettingsExpanded] =
useState(false);
const onCancel = useCallback(() => {
setIsNewAuthSessionModalOpen(false);
setRuntimeUrl("");
setAlias("");
- }, [setIsNewAuthSessionModalOpen]);
+ setClientId(env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID);
+ setScope(AUTH_SESSION_OIDC_DEFAULT_SCOPES);
+ setAudience("");
+ }, [env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
setIsNewAuthSessionModalOpen]);
const onConnect = useCallback<React.FormEventHandler>(
(e) => {
@@ -78,9 +87,11 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
await AuthSessionsService.authenticate({
runtimeUrl,
authServerUrl: checkResults.authServerUrl,
- clientId:
env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
+ clientId,
name: alias,
forceLoginPrompt,
+ audience,
+ scope,
loginSuccessRoute: routes.login.url({ base:
window.location.origin, pathParams: {} }),
});
} else {
@@ -98,7 +109,7 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
setIsNewAuthSessionModalOpen(false);
}
} catch (e) {
- console.log(e);
+ console.error(e);
setError(`Could not communicate with runtime running at
'${runtimeUrl}'`);
} finally {
setLoading(false);
@@ -111,8 +122,10 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
[
runtimeUrl,
alias,
+ clientId,
forceLoginPrompt,
- env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
+ audience,
+ scope,
routes.login,
add,
onAddAuthSession,
@@ -135,7 +148,7 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
autoFocus={true}
onChange={setAlias}
placeholder="Enter an alias..."
- tabIndex={1}
+ tabIndex={0}
/>
</FormGroup>
<FormGroup
@@ -145,7 +158,7 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
helperText={" "}
validated={error ? "error" : "default"}
>
- <TextInput id="url" aria-label="URL" tabIndex={2}
onChange={setRuntimeUrl} placeholder="Enter a URL..." />
+ <TextInput id="url" aria-label="URL" tabIndex={0}
onChange={setRuntimeUrl} placeholder="Enter a URL..." />
</FormGroup>
<FormGroup
isRequired={false}
@@ -164,10 +177,63 @@ export const NewAuthSessionModal: React.FC<Props> = ({
onAddAuthSession }) => {
Force login prompt <i>(for secured runtimes only)</i>
</span>
}
- tabIndex={3}
+ tabIndex={0}
/>
</FormGroup>
+ <ExpandableSection
+ toggleText={"Advanced OpenID Connect settings"}
+ onToggle={() => setIsAdvancedOIDCSettingsExpanded((currentValue) =>
!currentValue)}
+ isExpanded={isAdvancedOIDCSettingsExpanded}
+ >
+ <FormGroup
+ label="Client ID"
+ isRequired={true}
+ helperTextInvalid={error}
+ helperText={" "}
+ validated={error ? "error" : "default"}
+ >
+ <TextInput
+ id="clientId"
+ aria-label="Client ID"
+ value={clientId}
+ tabIndex={isAdvancedOIDCSettingsExpanded ? 0 : undefined}
+ onChange={setClientId}
+ />
+ </FormGroup>
+ <FormGroup
+ label="Scope"
+ isRequired={true}
+ helperTextInvalid={error}
+ helperText={" "}
+ validated={error ? "error" : "default"}
+ >
+ <TextInput
+ id="scope"
+ aria-label="Scope"
+ value={scope}
+ tabIndex={isAdvancedOIDCSettingsExpanded ? 0 : undefined}
+ onChange={setScope}
+ />
+ </FormGroup>
+ <FormGroup
+ label="Audience"
+ isRequired={false}
+ helperTextInvalid={error}
+ helperText={" "}
+ validated={error ? "error" : "default"}
+ >
+ <TextInput
+ id="audience"
+ aria-label="Audience"
+ value={audience}
+ tabIndex={isAdvancedOIDCSettingsExpanded ? 0 : undefined}
+ onChange={setAudience}
+ placeholder="The Audience (aud) or Identifier of the
application."
+ />
+ </FormGroup>
+ </ExpandableSection>
+
<ActionGroup>
<Button
type={ButtonType.submit}
diff --git
a/packages/runtime-tools-management-console-webapp/src/runtime/RuntimeContext.tsx
b/packages/runtime-tools-management-console-webapp/src/runtime/RuntimeContext.tsx
index 8f24e62c751..50dc39c455e 100644
---
a/packages/runtime-tools-management-console-webapp/src/runtime/RuntimeContext.tsx
+++
b/packages/runtime-tools-management-console-webapp/src/runtime/RuntimeContext.tsx
@@ -221,7 +221,7 @@ export const RuntimeContextProvider:
React.FC<RuntimeContextProviderProps> = (pr
setIsRefreshingToken(true);
const reauthResponse = await AuthSessionsService.reauthenticate({
authSession,
- clientId: env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
+ fromUnauthorizedRequest: true,
});
const updatedAuthSession: AuthSession = {
...authSession,
@@ -242,7 +242,7 @@ export const RuntimeContextProvider:
React.FC<RuntimeContextProviderProps> = (pr
setIsRefreshingToken(false);
}
},
- [env.RUNTIME_TOOLS_MANAGEMENT_CONSOLE_OIDC_CLIENT_CLIENT_ID,
updateAuthSession, history, routes.home]
+ [updateAuthSession, history, routes.home]
);
const onUnauthorized = useCallback(
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eec6a7b4caf..f79cd38edd4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8653,12 +8653,9 @@ importers:
history:
specifier: ^4.9.0
version: 4.10.1
- oidc-client-ts:
- specifier: ^3.1.0
- version: 3.1.0
openid-client:
- specifier: ^6.1.3
- version: 6.1.3
+ specifier: ^6.3.3
+ version: 6.3.3
react:
specifier: ^17.0.2
version: 17.0.2
@@ -25792,6 +25789,9 @@ packages:
[email protected]:
resolution: {integrity:
sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
+ [email protected]:
+ resolution: {integrity:
sha512-EyUPtOKyTYq+iMOszO42eobQllaIjJnwkZ2U93aJzNyPibCy7CEvT9UQnaCVB51IAd49gbNdCew1c0LcLTCB2g==}
+
[email protected]:
resolution: {integrity:
sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==}
@@ -27178,8 +27178,8 @@ packages:
engines: {node: ^18.12 || ^20 || ^22, yarn: ^1.15.2}
hasBin: true
- [email protected]:
- resolution: {integrity:
sha512-dik5wEMdFL5p3JlijYvM7wMNCgaPhblLIDCZtdXcaZp5wgu5Iwmsu7lMzgFhIDTi5d0BJo03LVoOoFQvXMeOeQ==}
+ [email protected]:
+ resolution: {integrity:
sha512-ZlozhPlFfobzh3hB72gnBFLjXpugl/dljz1fJSRdqaV2r3D5dmi5lg2QWI0LmUYuazmE+b5exsloEv6toUtw9g==}
[email protected]:
resolution: {integrity:
sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
@@ -27251,10 +27251,6 @@ packages:
[email protected]:
resolution: {integrity:
sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
- [email protected]:
- resolution: {integrity:
sha512-IDopEXjiwjkmJLYZo6BTlvwOtnlSniWZkKZoXforC/oLZHC9wkIxd25Kwtmo5yKFMMVcsp3JY6bhcNJqdYk8+g==}
- engines: {node: '>=18'}
-
[email protected]:
resolution: {integrity:
sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
engines: {node: '>= 0.8'}
@@ -27312,8 +27308,8 @@ packages:
resolution: {integrity:
sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
hasBin: true
- [email protected]:
- resolution: {integrity:
sha512-74sc0bR4ptfwCwMheLPaJHTQnds+97Yu6O8eQgoO3MRcd53xkfKyl3gNAsRsYSYoO+AVG3eCgnRMjRkZ6n2RYw==}
+ [email protected]:
+ resolution: {integrity:
sha512-lTK8AV8SjqCM4qznLX0asVESAwzV39XTVdfMAM185ekuaZCnkWdPzcxMTXNlsm9tsUAMa1Q30MBmKAykdT1LWw==}
[email protected]:
resolution: {integrity:
sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==}
@@ -51851,6 +51847,8 @@ snapshots:
[email protected]: {}
+ [email protected]: {}
+
[email protected]: {}
[email protected]: {}
@@ -53586,7 +53584,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- [email protected]: {}
+ [email protected]: {}
[email protected]: {}
@@ -53675,10 +53673,6 @@ snapshots:
[email protected]: {}
- [email protected]:
- dependencies:
- jwt-decode: 4.0.0
-
[email protected]:
dependencies:
ee-first: 1.1.1
@@ -53742,10 +53736,10 @@ snapshots:
[email protected]: {}
- [email protected]:
+ [email protected]:
dependencies:
- jose: 5.9.6
- oauth4webapi: 3.1.3
+ jose: 6.0.8
+ oauth4webapi: 3.3.0
[email protected]:
dependencies:
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]