From 5e72dce0decd6a60c1ef048c74e6560352b43eb1 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Fri, 5 Sep 2025 19:42:47 +0100 Subject: [PATCH] login_fix (#4402) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../service/CustomUserDetailsService.java | 46 ++++++++++++++++++- build.gradle | 2 +- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java index 1704e5972..df3934bbd 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; +import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.database.repository.UserRepository; import stirling.software.proprietary.security.model.AuthenticationType; import stirling.software.proprietary.security.model.User; @@ -20,6 +21,8 @@ public class CustomUserDetailsService implements UserDetailsService { private final LoginAttemptService loginAttemptService; + private final ApplicationProperties.Security securityProperties; + @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = @@ -35,12 +38,53 @@ public class CustomUserDetailsService implements UserDetailsService { "Your account has been locked due to too many failed login attempts."); } + // Handle legacy users without authenticationType (from versions < 1.3.0) + String authTypeStr = user.getAuthenticationType(); + if (authTypeStr == null || authTypeStr.isEmpty()) { + // Migrate legacy users by detecting authentication type based on password presence + AuthenticationType detectedType; + if (user.hasPassword()) { + // Users with passwords are likely traditional web authentication users + detectedType = AuthenticationType.WEB; + } else { + // Users without passwords are SSO users (OAuth2/SAML2/etc) + // Choose the appropriate SSO type based on what's enabled + detectedType = determinePreferredSSOType(); + } + + authTypeStr = detectedType.name(); + // Update the user record to set the detected authentication type + user.setAuthenticationType(detectedType); + userRepository.save(user); + } + AuthenticationType userAuthenticationType = - AuthenticationType.valueOf(user.getAuthenticationType().toUpperCase()); + AuthenticationType.valueOf(authTypeStr.toUpperCase()); if (!user.hasPassword() && userAuthenticationType == AuthenticationType.WEB) { throw new IllegalArgumentException("Password must not be null"); } return user; } + + /** + * Determines the preferred SSO authentication type based on what's enabled in the application + * configuration. + * + * @return The preferred AuthenticationType for SSO users + */ + private AuthenticationType determinePreferredSSOType() { + // Check what SSO types are enabled and prefer in order: OAUTH2 > SAML2 > fallback to OAUTH2 + boolean oauth2Enabled = securityProperties.getOauth2() != null && securityProperties.getOauth2().getEnabled(); + boolean saml2Enabled = securityProperties.getSaml2() != null && securityProperties.getSaml2().getEnabled(); + + if (oauth2Enabled) { + return AuthenticationType.OAUTH2; + } else if (saml2Enabled) { + return AuthenticationType.SAML2; + } else { + // Fallback to OAUTH2 (better than deprecated SSO) + return AuthenticationType.OAUTH2; + } + } } diff --git a/build.gradle b/build.gradle index 76c425335..af8962dc9 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,7 @@ repositories { allprojects { group = 'stirling.software' - version = '1.3.1' + version = '1.3.2' configurations.configureEach { exclude group: 'commons-logging', module: 'commons-logging'