diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java index 88260ea5b..067c8bde0 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java @@ -158,8 +158,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { String clientId = null; OAUTH2 oauth = applicationProperties.getSecurity().getOauth2(); - if (authentication instanceof OAuth2AuthenticationToken) { - OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication; + if (authentication instanceof OAuth2AuthenticationToken oauthToken) { registrationId = oauthToken.getAuthorizedClientRegistrationId(); try { 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 a45019bca..bd1962f6f 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -414,33 +414,41 @@ public class UserService implements UserServiceInterface { } @Transactional - public void syncCustomApiUser(String customApiKey) - throws SQLException, UnsupportedProviderException { - if (customApiKey == null || customApiKey.trim().length() == 0) { + public void syncCustomApiUser(String customApiKey) { + if (customApiKey == null || customApiKey.trim().isBlank()) { return; } + String username = "CUSTOM_API_USER"; Optional existingUser = findByUsernameIgnoreCase(username); - if (!existingUser.isPresent()) { - // Create new user with API role - User user = new User(); - user.setUsername(username); - user.setPassword(UUID.randomUUID().toString()); - user.setEnabled(true); - user.setFirstLogin(false); - user.setAuthenticationType(AuthenticationType.WEB); - user.setApiKey(customApiKey); - user.addAuthority(new Authority(Role.INTERNAL_API_USER.getRoleId(), user)); - userRepository.save(user); + + existingUser.ifPresentOrElse( + user -> { + // Update API key if it has changed + User updatedUser = existingUser.get(); + + if (!customApiKey.equals(updatedUser.getApiKey())) { + updatedUser.setApiKey(customApiKey); + userRepository.save(updatedUser); + } + }, + () -> { + // Create new user with API role + User user = new User(); + user.setUsername(username); + user.setPassword(UUID.randomUUID().toString()); + user.setEnabled(true); + user.setFirstLogin(false); + user.setAuthenticationType(AuthenticationType.WEB); + user.setApiKey(customApiKey); + user.addAuthority(new Authority(Role.INTERNAL_API_USER.getRoleId(), user)); + userRepository.save(user); + }); + + try { databaseService.exportDatabase(); - } else { - // Update API key if it has changed - User user = existingUser.get(); - if (!customApiKey.equals(user.getApiKey())) { - user.setApiKey(customApiKey); - userRepository.save(user); - databaseService.exportDatabase(); - } + } catch (SQLException | UnsupportedProviderException e) { + log.error("Error exporting database after synchronising custom API user", e); } } diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index 8c40137ce..75b7ec006 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -48,11 +48,9 @@ public class CustomOAuth2AuthenticationSuccessHandler Object principal = authentication.getPrincipal(); String username = ""; - if (principal instanceof OAuth2User) { - OAuth2User oauthUser = (OAuth2User) principal; + if (principal instanceof OAuth2User oauthUser) { username = oauthUser.getName(); - } else if (principal instanceof UserDetails) { - UserDetails oauthUser = (UserDetails) principal; + } else if (principal instanceof UserDetails oauthUser) { username = oauthUser.getUsername(); } diff --git a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java index 2c683b387..eab62c8eb 100644 --- a/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/oauth2/CustomOAuth2UserService.java @@ -44,6 +44,7 @@ public class CustomOAuth2UserService implements OAuth2UserService registrations = new ArrayList<>(); githubClientRegistration().ifPresent(registrations::add); oidcClientRegistration().ifPresent(registrations::add); googleClientRegistration().ifPresent(registrations::add); keycloakClientRegistration().ifPresent(registrations::add); + if (registrations.isEmpty()) { log.error("At least one OAuth2 provider must be configured"); System.exit(1); @@ -169,6 +164,10 @@ public class OAuth2Configuration { .scope(oauth.getScopes()) .userNameAttributeName(oauth.getUseAsUsername()) .clientName("OIDC") + .redirectUri("{baseUrl}/login/oauth2/code/oidc") + .authorizationGrantType( + org.springframework.security.oauth2.core.AuthorizationGrantType + .AUTHORIZATION_CODE) .build()); } diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template index f6e2bb0f5..8a023f9f6 100644 --- a/src/main/resources/settings.yml.template +++ b/src/main/resources/settings.yml.template @@ -12,11 +12,11 @@ security: - enableLogin: false # set to 'true' to enable login + enableLogin: true # set to 'true' to enable login csrfDisabled: false # set to 'true' to disable CSRF protection (not recommended for production) loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1 loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts - loginMethod: all # Accepts values like 'all' and 'normal'(only Login with Username/Password), 'oauth2'(only Login with OAuth2) or 'saml2'(only Login with SAML2) + loginMethod: saml2 # Accepts values like 'all' and 'normal'(only Login with Username/Password), 'oauth2'(only Login with OAuth2) or 'saml2'(only Login with SAML2) initialLogin: username: '' # initial username for the first login password: '' # initial password for the first login