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 ?? "")}
-                  &nbsp;
-                  <small>{`(...plus ${(props.authSession.tokens.refresh_token 
?? "").length - 16} hidden characters)`}</small>
+                  {props.authSession.tokens.refresh_token ? (
+                    <>
+                      {obfuscate(props.authSession.tokens.refresh_token ?? "")}
+                      &nbsp;
+                      <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]

Reply via email to