diff --git a/PostFundManagement.ConsoleUI/.env.example b/PostFundManagement.ConsoleUI/.env.example index 0f6d60e..2f34f97 100644 --- a/PostFundManagement.ConsoleUI/.env.example +++ b/PostFundManagement.ConsoleUI/.env.example @@ -12,7 +12,6 @@ APP_URL="MY_APP_URL" VITE_OIDC_AUTHORITY="https://sts.security.khongisa.co.za" VITE_OIDC_AUDIENCE="pfm-api-dev" VITE_OIDC_CLIENT_ID="pfm-scalar-dev" -VITE_OIDC_CLIENT_SECRET="secret_71f88570a46eb22eb5270b47f69e3332c84d8db85d008f0276cb7431c8872d27" # PFM Backend API Base URL VITE_API_BASE_URL="https://api.ifri.khongisa.co.za/" diff --git a/PostFundManagement.ConsoleUI/docker-entrypoint.sh b/PostFundManagement.ConsoleUI/docker-entrypoint.sh index 7348227..1fafebd 100644 --- a/PostFundManagement.ConsoleUI/docker-entrypoint.sh +++ b/PostFundManagement.ConsoleUI/docker-entrypoint.sh @@ -26,13 +26,10 @@ OIDC_AUDIENCE="${VITE_OIDC_AUDIENCE:-${OIDC_AUDIENCE:-${SecuritySettings__Audien # 4. OIDC Client ID OIDC_CLIENT_ID="${VITE_OIDC_CLIENT_ID:-${OIDC_CLIENT_ID:-${SecuritySettings__ClientId:-${SecuritySettings_ClientId:-${CLIENT_ID:-}}}}}" -# 5. OIDC Client Secret -OIDC_CLIENT_SECRET="${VITE_OIDC_CLIENT_SECRET:-${OIDC_CLIENT_SECRET:-${SecuritySettings__ClientSecret:-${SecuritySettings_ClientSecret:-${CLIENT_SECRET:-}}}}}" - -# 6. OIDC Scope +# 5. OIDC Scope OIDC_SCOPE="${VITE_OIDC_SCOPE:-${OIDC_SCOPE:-${SecuritySettings__Scope:-${SecuritySettings_Scope:-${SCOPE:-}}}}}" -# 7. Hasher Settings +# 6. Hasher Settings HASHER_SALT="${VITE_HASHER_SALT:-${HASHER_SALT:-${HasherSettings__Salt:-${HasherSettings_Salt:-}}}}}" HASHER_MIN_LENGTH="${VITE_HASHER_MIN_LENGTH:-${HASHER_MIN_LENGTH:-${HasherSettings__MinLength:-${HasherSettings_MinLength:-}}}}}" @@ -40,8 +37,10 @@ if [ -d "$TARGET_DIR" ]; then echo "[docker-entrypoint] Generating runtime configuration files in $TARGET_DIR..." # Generate env-config.js for instant, synchronous window.__RUNTIME_CONFIG__ initialization + # Public SPA clients use Authorization Code flow with PKCE; client secrets must NEVER be injected or exposed here. cat < "$TARGET_DIR/env-config.js" // Generated dynamically at container startup from deployment environment variables +// Note: Secrets such as client secrets or private keys must NEVER be exposed here. window.__RUNTIME_CONFIG__ = { API_BASE_URL: "${API_BASE_URL}", VITE_API_BASE_URL: "${API_BASE_URL}", @@ -51,8 +50,6 @@ window.__RUNTIME_CONFIG__ = { VITE_OIDC_AUDIENCE: "${OIDC_AUDIENCE}", OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}", VITE_OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}", - OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}", - VITE_OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}", OIDC_SCOPE: "${OIDC_SCOPE}", VITE_OIDC_SCOPE: "${OIDC_SCOPE}", HASHER_SALT: "${HASHER_SALT}", @@ -66,7 +63,6 @@ window.__RUNTIME_CONFIG__ = { Authority: "${OIDC_AUTHORITY}", Audience: "${OIDC_AUDIENCE}", ClientId: "${OIDC_CLIENT_ID}", - ClientSecret: "${OIDC_CLIENT_SECRET}", Scope: "${OIDC_SCOPE}" }, HasherSettings: { @@ -86,7 +82,6 @@ EOF "Authority": "${OIDC_AUTHORITY}", "Audience": "${OIDC_AUDIENCE}", "ClientId": "${OIDC_CLIENT_ID}", - "ClientSecret": "${OIDC_CLIENT_SECRET}", "Scope": "${OIDC_SCOPE}" }, "HasherSettings": { diff --git a/PostFundManagement.ConsoleUI/public/config.json b/PostFundManagement.ConsoleUI/public/config.json index dd80e47..068597f 100644 --- a/PostFundManagement.ConsoleUI/public/config.json +++ b/PostFundManagement.ConsoleUI/public/config.json @@ -6,7 +6,6 @@ "Authority": "", "Audience": "", "ClientId": "", - "ClientSecret": "", "Scope": "" }, "HasherSettings": { diff --git a/PostFundManagement.ConsoleUI/src/auth/AuthProvider.tsx b/PostFundManagement.ConsoleUI/src/auth/AuthProvider.tsx index 91ebb38..5045b61 100644 --- a/PostFundManagement.ConsoleUI/src/auth/AuthProvider.tsx +++ b/PostFundManagement.ConsoleUI/src/auth/AuthProvider.tsx @@ -320,7 +320,7 @@ export function getUserManager(): UserManager { userManagerInstance = new UserManager({ authority: sec.Authority, client_id: sec.ClientId, - client_secret: sec.ClientSecret, + ...(sec.ClientSecret ? { client_secret: sec.ClientSecret } : {}), redirect_uri: `${origin}/dashboard`, post_logout_redirect_uri: `${origin}/`, response_type: 'code', diff --git a/PostFundManagement.ConsoleUI/src/config.ts b/PostFundManagement.ConsoleUI/src/config.ts index c3f2ab1..062cb94 100644 --- a/PostFundManagement.ConsoleUI/src/config.ts +++ b/PostFundManagement.ConsoleUI/src/config.ts @@ -4,7 +4,7 @@ export interface SecuritySettings { Authority: string; Audience: string; ClientId: string; - ClientSecret: string; + ClientSecret?: string; Scope?: string; } @@ -36,7 +36,6 @@ export const defaultSecuritySettings: SecuritySettings = { Authority: 'https://sts.security.khongisa.co.za', Audience: 'pfm-api-dev', ClientId: 'pfm-console-dev', - ClientSecret: 'secret_dcaeaa28097d9ba5b06ec324d9eac9d9c81de96e0a203cf2c6154c6dd7c89e94', Scope: 'openid profile roles email address pfm-api-dev', }; @@ -255,9 +254,8 @@ function resolveConfig(fetchedJson?: Record): AppConfig { const clientSecret = pickFirstNonEmpty( windowConfig.clientSecret, fetchedConfig.clientSecret, - buildEnvConfig.clientSecret, - defaultSecuritySettings.ClientSecret - )!; + buildEnvConfig.clientSecret + ); const scope = pickFirstNonEmpty( windowConfig.scope, @@ -291,7 +289,7 @@ function resolveConfig(fetchedJson?: Record): AppConfig { Authority: normalizeAuthorityUrl(authority), Audience: audience, ClientId: clientId, - ClientSecret: clientSecret, + ...(clientSecret ? { ClientSecret: clientSecret } : {}), Scope: scope, }, ApiSettings: { diff --git a/PostFundManagement.ConsoleUI/src/vite-env.d.ts b/PostFundManagement.ConsoleUI/src/vite-env.d.ts index d57366f..0c85328 100644 --- a/PostFundManagement.ConsoleUI/src/vite-env.d.ts +++ b/PostFundManagement.ConsoleUI/src/vite-env.d.ts @@ -4,7 +4,6 @@ interface ImportMetaEnv { readonly VITE_OIDC_AUTHORITY?: string; readonly VITE_OIDC_AUDIENCE?: string; readonly VITE_OIDC_CLIENT_ID?: string; - readonly VITE_OIDC_CLIENT_SECRET?: string; readonly VITE_API_BASE_URL?: string; } diff --git a/PostFundManagement.PartnerUI/docker-entrypoint.sh b/PostFundManagement.PartnerUI/docker-entrypoint.sh index 7348227..1fafebd 100644 --- a/PostFundManagement.PartnerUI/docker-entrypoint.sh +++ b/PostFundManagement.PartnerUI/docker-entrypoint.sh @@ -26,13 +26,10 @@ OIDC_AUDIENCE="${VITE_OIDC_AUDIENCE:-${OIDC_AUDIENCE:-${SecuritySettings__Audien # 4. OIDC Client ID OIDC_CLIENT_ID="${VITE_OIDC_CLIENT_ID:-${OIDC_CLIENT_ID:-${SecuritySettings__ClientId:-${SecuritySettings_ClientId:-${CLIENT_ID:-}}}}}" -# 5. OIDC Client Secret -OIDC_CLIENT_SECRET="${VITE_OIDC_CLIENT_SECRET:-${OIDC_CLIENT_SECRET:-${SecuritySettings__ClientSecret:-${SecuritySettings_ClientSecret:-${CLIENT_SECRET:-}}}}}" - -# 6. OIDC Scope +# 5. OIDC Scope OIDC_SCOPE="${VITE_OIDC_SCOPE:-${OIDC_SCOPE:-${SecuritySettings__Scope:-${SecuritySettings_Scope:-${SCOPE:-}}}}}" -# 7. Hasher Settings +# 6. Hasher Settings HASHER_SALT="${VITE_HASHER_SALT:-${HASHER_SALT:-${HasherSettings__Salt:-${HasherSettings_Salt:-}}}}}" HASHER_MIN_LENGTH="${VITE_HASHER_MIN_LENGTH:-${HASHER_MIN_LENGTH:-${HasherSettings__MinLength:-${HasherSettings_MinLength:-}}}}}" @@ -40,8 +37,10 @@ if [ -d "$TARGET_DIR" ]; then echo "[docker-entrypoint] Generating runtime configuration files in $TARGET_DIR..." # Generate env-config.js for instant, synchronous window.__RUNTIME_CONFIG__ initialization + # Public SPA clients use Authorization Code flow with PKCE; client secrets must NEVER be injected or exposed here. cat < "$TARGET_DIR/env-config.js" // Generated dynamically at container startup from deployment environment variables +// Note: Secrets such as client secrets or private keys must NEVER be exposed here. window.__RUNTIME_CONFIG__ = { API_BASE_URL: "${API_BASE_URL}", VITE_API_BASE_URL: "${API_BASE_URL}", @@ -51,8 +50,6 @@ window.__RUNTIME_CONFIG__ = { VITE_OIDC_AUDIENCE: "${OIDC_AUDIENCE}", OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}", VITE_OIDC_CLIENT_ID: "${OIDC_CLIENT_ID}", - OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}", - VITE_OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET}", OIDC_SCOPE: "${OIDC_SCOPE}", VITE_OIDC_SCOPE: "${OIDC_SCOPE}", HASHER_SALT: "${HASHER_SALT}", @@ -66,7 +63,6 @@ window.__RUNTIME_CONFIG__ = { Authority: "${OIDC_AUTHORITY}", Audience: "${OIDC_AUDIENCE}", ClientId: "${OIDC_CLIENT_ID}", - ClientSecret: "${OIDC_CLIENT_SECRET}", Scope: "${OIDC_SCOPE}" }, HasherSettings: { @@ -86,7 +82,6 @@ EOF "Authority": "${OIDC_AUTHORITY}", "Audience": "${OIDC_AUDIENCE}", "ClientId": "${OIDC_CLIENT_ID}", - "ClientSecret": "${OIDC_CLIENT_SECRET}", "Scope": "${OIDC_SCOPE}" }, "HasherSettings": { diff --git a/PostFundManagement.PartnerUI/public/config.json b/PostFundManagement.PartnerUI/public/config.json index e49fbd4..64de53d 100644 --- a/PostFundManagement.PartnerUI/public/config.json +++ b/PostFundManagement.PartnerUI/public/config.json @@ -4,7 +4,6 @@ "Authority": "", "Audience": "", "ClientId": "", - "ClientSecret": "", "Scope": "" }, "ApiSettings": { diff --git a/PostFundManagement.PartnerUI/src/auth/AuthProvider.tsx b/PostFundManagement.PartnerUI/src/auth/AuthProvider.tsx index 4a11911..d94b513 100644 --- a/PostFundManagement.PartnerUI/src/auth/AuthProvider.tsx +++ b/PostFundManagement.PartnerUI/src/auth/AuthProvider.tsx @@ -322,7 +322,7 @@ export function getUserManager(): UserManager { userManagerInstance = new UserManager({ authority: sec.Authority, client_id: sec.ClientId, - client_secret: sec.ClientSecret, + ...(sec.ClientSecret ? { client_secret: sec.ClientSecret } : {}), redirect_uri: `${origin}/dashboard`, post_logout_redirect_uri: `${origin}/`, response_type: 'code', diff --git a/PostFundManagement.PartnerUI/src/config.ts b/PostFundManagement.PartnerUI/src/config.ts index 6ee8257..eac650e 100644 --- a/PostFundManagement.PartnerUI/src/config.ts +++ b/PostFundManagement.PartnerUI/src/config.ts @@ -5,7 +5,7 @@ export interface SecuritySettings { Authority: string; Audience: string; ClientId: string; - ClientSecret: string; + ClientSecret?: string; Scope?: string; } @@ -32,7 +32,6 @@ export const defaultSecuritySettings: SecuritySettings = { Authority: 'https://sts.security.khongisa.co.za', Audience: 'pfm-api-dev', ClientId: 'pfm-console-dev', - ClientSecret: 'secret_dcaeaa28097d9ba5b06ec324d9eac9d9c81de96e0a203cf2c6154c6dd7c89e94', Scope: 'openid profile roles email address pfm-api-dev', }; @@ -218,9 +217,8 @@ function resolveConfig(fetchedJson?: Record): AppConfig { const clientSecret = pickFirstNonEmpty( winCfg.clientSecret, fetchCfg.clientSecret, - envCfg.clientSecret, - defaultSecuritySettings.ClientSecret - )!; + envCfg.clientSecret + ); const scope = pickFirstNonEmpty( winCfg.scope, fetchCfg.scope, @@ -247,7 +245,7 @@ function resolveConfig(fetchedJson?: Record): AppConfig { Authority: authority, Audience: audience, ClientId: clientId, - ClientSecret: clientSecret, + ...(clientSecret ? { ClientSecret: clientSecret } : {}), Scope: scope, }, ApiSettings: {