diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml index 7743ca9b1..4f81d64a3 100644 --- a/frontend/public/locales/en-GB/translation.toml +++ b/frontend/public/locales/en-GB/translation.toml @@ -449,6 +449,7 @@ required = "All fields are required." mismatch = "New passwords do not match." error = "Unable to update password. Please verify your current password and try again." success = "Password updated successfully. Please sign in again." +ssoDisabled = "Password changes are managed by your identity provider." current = "Current password" currentPlaceholder = "Enter your current password" new = "New password" @@ -510,6 +511,7 @@ low = "Low" title = "Change Credentials" header = "Update Your Account Details" changePassword = "You are using default login credentials. Please enter a new password" +ssoManaged = "Your account is managed by your identity provider." newUsername = "New Username" oldPassword = "Current Password" newPassword = "New Password" diff --git a/frontend/src/proprietary/auth/springAuthClient.ts b/frontend/src/proprietary/auth/springAuthClient.ts index 1ba2b909a..f77e34cb6 100644 --- a/frontend/src/proprietary/auth/springAuthClient.ts +++ b/frontend/src/proprietary/auth/springAuthClient.ts @@ -60,6 +60,7 @@ export interface User { enabled?: boolean; is_anonymous?: boolean; isFirstLogin?: boolean; + authenticationType?: string; app_metadata?: Record; } diff --git a/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx index f627302b4..95a9ee57f 100644 --- a/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx +++ b/frontend/src/proprietary/components/shared/config/configSections/AccountSection.tsx @@ -24,6 +24,17 @@ const AccountSection: React.FC = () => { const [usernameError, setUsernameError] = useState(''); const [usernameSubmitting, setUsernameSubmitting] = useState(false); + const authTypeFromMetadata = useMemo(() => { + const metadata = user?.app_metadata as { authType?: string; authenticationType?: string } | undefined; + return metadata?.authenticationType ?? metadata?.authType; + }, [user?.app_metadata]); + + const normalizedAuthType = useMemo( + () => (user?.authenticationType ?? authTypeFromMetadata ?? '').toLowerCase(), + [authTypeFromMetadata, user?.authenticationType] + ); + const isSsoUser = useMemo(() => ['sso', 'oauth2', 'saml2'].includes(normalizedAuthType), [normalizedAuthType]); + const userIdentifier = useMemo(() => user?.email || user?.username || '', [user?.email, user?.username]); const redirectToLogin = useCallback(() => { @@ -41,6 +52,11 @@ const AccountSection: React.FC = () => { const handlePasswordSubmit = async (event: React.FormEvent) => { event.preventDefault(); + if (isSsoUser) { + setPasswordError(t('settings.security.password.ssoDisabled', 'Password changes are managed by your identity provider.')); + return; + } + if (!currentPassword || !newPassword || !confirmPassword) { setPasswordError(t('settings.security.password.required', 'All fields are required.')); return; @@ -81,6 +97,11 @@ const AccountSection: React.FC = () => { const handleUsernameSubmit = async (event: React.FormEvent) => { event.preventDefault(); + if (isSsoUser) { + setUsernameError(t('changeCreds.ssoManaged', 'Your account is managed by your identity provider.')); + return; + } + if (!currentPasswordForUsername || !newUsername) { setUsernameError(t('settings.security.password.required', 'All fields are required.')); return; @@ -132,23 +153,35 @@ const AccountSection: React.FC = () => { : t('account.accountSettings', 'Account Settings')} - - + + {isSsoUser && ( + } color="blue" variant="light"> + {t('changeCreds.ssoManaged', 'Your account is managed by your identity provider.')} + + )} - + + {!isSsoUser && ( + + )} - - + {!isSsoUser && ( + + )} + + + +