From ace4e200b130a8006778121de4c2692ffe13242d Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 14 Apr 2024 23:07:03 +0200 Subject: [PATCH] Fix: Resolve Username Case Sensitivity Issue in Login Flow (#1070) * Fix: Username changing The only situation where the username must be unique is when changing the username. * Update UserController.java --- .../CustomAuthenticationFailureHandler.java | 2 +- .../SPDF/config/security/FirstLoginFilter.java | 2 +- .../config/security/InitialSecuritySetup.java | 2 +- .../SPDF/config/security/UserService.java | 14 +++++++++----- .../SPDF/controller/api/UserController.java | 15 ++++++++------- .../SPDF/controller/web/AccountWebController.java | 4 ++-- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java index 038e087f6..f4f5a37df 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java @@ -56,7 +56,7 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF } private boolean isDemoUser(String username) { - Optional user = userService.findByUsername(username); + Optional user = userService.findByUsernameIgnoreCase(username); return user.isPresent() && user.get().getAuthorities().stream() .anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority())); diff --git a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java b/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java index b272327af..5936ea3fb 100644 --- a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java @@ -39,7 +39,7 @@ public class FirstLoginFilter extends OncePerRequestFilter { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { - Optional user = userService.findByUsername(authentication.getName()); + Optional user = userService.findByUsernameIgnoreCase(authentication.getName()); if ("GET".equalsIgnoreCase(method) && user.isPresent() && user.get().isFirstLogin() diff --git a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java index 3b396b157..0d87ca482 100644 --- a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java +++ b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java @@ -38,7 +38,7 @@ public class InitialSecuritySetup { initialUsername, initialPassword, Role.ADMIN.getRoleId(), true); } } - if (!userService.usernameExists(Role.INTERNAL_API_USER.getRoleId())) { + if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) { userService.saveUser( Role.INTERNAL_API_USER.getRoleId(), UUID.randomUUID().toString(), diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/src/main/java/stirling/software/SPDF/config/security/UserService.java index 666baa934..83f38bd74 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -62,7 +62,7 @@ public class UserService implements UserServiceInterface { public User addApiKeyToUser(String username) { User user = userRepository - .findByUsername(username) + .findByUsernameIgnoreCase(username) .orElseThrow(() -> new UsernameNotFoundException("User not found")); user.setApiKey(generateApiKey()); @@ -76,7 +76,7 @@ public class UserService implements UserServiceInterface { public String getApiKeyForUser(String username) { User user = userRepository - .findByUsername(username) + .findByUsernameIgnoreCase(username) .orElseThrow(() -> new UsernameNotFoundException("User not found")); return user.getApiKey(); } @@ -103,7 +103,7 @@ public class UserService implements UserServiceInterface { } public boolean validateApiKeyForUser(String username, String apiKey) { - Optional userOpt = userRepository.findByUsername(username); + Optional userOpt = userRepository.findByUsernameIgnoreCase(username); return userOpt.isPresent() && userOpt.get().getApiKey().equals(apiKey); } @@ -136,7 +136,7 @@ public class UserService implements UserServiceInterface { } public void deleteUser(String username) { - Optional userOpt = userRepository.findByUsername(username); + Optional userOpt = userRepository.findByUsernameIgnoreCase(username); if (userOpt.isPresent()) { for (Authority authority : userOpt.get().getAuthorities()) { if (authority.getAuthority().equals(Role.INTERNAL_API_USER.getRoleId())) { @@ -151,12 +151,16 @@ public class UserService implements UserServiceInterface { return userRepository.findByUsername(username).isPresent(); } + public boolean usernameExistsIgnoreCase(String username) { + return userRepository.findByUsernameIgnoreCase(username).isPresent(); + } + public boolean hasUsers() { return userRepository.count() > 0; } public void updateUserSettings(String username, Map updates) { - Optional userOpt = userRepository.findByUsername(username); + Optional userOpt = userRepository.findByUsernameIgnoreCase(username); if (userOpt.isPresent()) { User user = userOpt.get(); Map settingsMap = user.getSettings(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/UserController.java b/src/main/java/stirling/software/SPDF/controller/api/UserController.java index 598a832d8..a7a40a0af 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/UserController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/UserController.java @@ -43,7 +43,7 @@ public class UserController { @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PostMapping("/register") public String register(@ModelAttribute UsernameAndPass requestModel, Model model) { - if (userService.usernameExists(requestModel.getUsername())) { + if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) { model.addAttribute("error", "Username already exists"); return "register"; } @@ -70,7 +70,8 @@ public class UserController { return new RedirectView("/account?messageType=notAuthenticated"); } - Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName()); + // The username MUST be unique when renaming + Optional userOpt = userService.findByUsername(principal.getName()); if (userOpt == null || userOpt.isEmpty()) { return new RedirectView("/account?messageType=userNotFound"); @@ -113,7 +114,7 @@ public class UserController { return new RedirectView("/change-creds?messageType=notAuthenticated"); } - Optional userOpt = userService.findByUsername(principal.getName()); + Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName()); if (userOpt == null || userOpt.isEmpty()) { return new RedirectView("/change-creds?messageType=userNotFound"); @@ -146,7 +147,7 @@ public class UserController { return new RedirectView("/account?messageType=notAuthenticated"); } - Optional userOpt = userService.findByUsername(principal.getName()); + Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName()); if (userOpt == null || userOpt.isEmpty()) { return new RedirectView("/account?messageType=userNotFound"); @@ -207,7 +208,7 @@ public class UserController { return new RedirectView("/addUsers?messageType=usernameExists"); } } - if (userService.usernameExists(username)) { + if (userService.usernameExistsIgnoreCase(username)) { return new RedirectView("/addUsers?messageType=usernameExists"); } try { @@ -231,7 +232,7 @@ public class UserController { public RedirectView deleteUser( @PathVariable(name = "username") String username, Authentication authentication) { - if (!userService.usernameExists(username)) { + if (!userService.usernameExistsIgnoreCase(username)) { return new RedirectView("/addUsers?messageType=deleteUsernameExists"); } @@ -239,7 +240,7 @@ public class UserController { String currentUsername = authentication.getName(); // Check if the provided username matches the current session's username - if (currentUsername.equals(username)) { + if (currentUsername.equalsIgnoreCase(username)) { return new RedirectView("/addUsers?messageType=deleteCurrentUser"); } invalidateUserSessions(username); diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java index d27f510a7..c9ffc19d0 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java @@ -95,7 +95,7 @@ public class AccountWebController { // Fetch user details from the database Optional user = - userRepository.findByUsername( + userRepository.findByUsernameIgnoreCase( username); // Assuming findByUsername method exists if (!user.isPresent()) { // Handle error appropriately @@ -145,7 +145,7 @@ public class AccountWebController { // Fetch user details from the database Optional user = - userRepository.findByUsername( + userRepository.findByUsernameIgnoreCase( username); // Assuming findByUsername method exists if (!user.isPresent()) { // Handle error appropriately