oauth to saml and compare fixes etc

This commit is contained in:
Anthony Stirling
2024-11-28 19:27:37 +00:00
parent 2885fac30d
commit d20e8f7d54
13 changed files with 56 additions and 55 deletions

View File

@@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
import stirling.software.SPDF.model.ApplicationProperties;
@@ -30,6 +31,7 @@ public class InitialSecuritySetup {
initializeAdminUser();
} else {
databaseBackupHelper.exportDatabase();
userService.migrateOauth2ToSSO();
}
initializeInternalApiUser();
}
@@ -75,4 +77,7 @@ public class InitialSecuritySetup {
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
}
}
}

View File

@@ -107,13 +107,14 @@ public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
if (applicationProperties.getSecurity().getCsrfDisabled()) {
http.csrf(csrf -> csrf.disable());
}
if (loginEnabledValue) {
http.addFilterBefore(
userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
if (applicationProperties.getSecurity().getCsrfDisabled()) {
http.csrf(csrf -> csrf.disable());
} else {
if (!applicationProperties.getSecurity().getCsrfDisabled()) {
CookieCsrfTokenRepository cookieRepo =
CookieCsrfTokenRepository.withHttpOnlyFalse();
CsrfTokenRequestAttributeHandler requestHandler =
@@ -268,11 +269,10 @@ public class SecurityConfiguration {
try {
saml2
.loginPage("/saml2")
// Add this
.relyingPartyRegistrationRepository(relyingPartyRegistrations())
.authenticationRequestResolver(new OpenSaml4AuthenticationRequestResolver(
relyingPartyRegistrations()
))
//.authenticationRequestResolver(new OpenSaml4AuthenticationRequestResolver(
// relyingPartyRegistrations()
// ))
.successHandler(
new CustomSaml2AuthenticationSuccessHandler(
loginAttemptService,
@@ -284,16 +284,10 @@ public class SecurityConfiguration {
} catch (Exception e) {
e.printStackTrace();
}
})
.saml2Logout(logout -> logout
.logoutUrl("/logout"))
;
});
}
} else {
if (applicationProperties.getSecurity().getCsrfDisabled()) {
http.csrf(csrf -> csrf.disable());
} else {
if (!applicationProperties.getSecurity().getCsrfDisabled()) {
CookieCsrfTokenRepository cookieRepo =
CookieCsrfTokenRepository.withHttpOnlyFalse();
CsrfTokenRequestAttributeHandler requestHandler =
@@ -316,19 +310,6 @@ public class SecurityConfiguration {
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
provider.setResponseAuthenticationConverter(
new CustomSaml2ResponseAuthenticationConverter(userService));
provider.setAssertionValidator(token -> {
try {
HashMap<String, Object> params = new HashMap<>();
// Add 5 minutes clock skew
params.put(Saml2ErrorCodes.INVALID_ASSERTION, Duration.ofMinutes(5));
ValidationContext context = new ValidationContext(params);
return Saml2ResponseValidatorResult.success();
} catch (Exception e) {
return Saml2ResponseValidatorResult.failure();
}
});
return provider;
}
// Client Registration Repository for OAUTH2 OIDC Login
@@ -489,7 +470,7 @@ public class SecurityConfiguration {
.entityId(samlConf.getIdpIssuer())
.singleSignOnServiceLocation(samlConf.getIdpSingleLoginUrl())
.verificationX509Credentials(c -> c.add(verificationCredential))
.singleSignOnServiceBinding(Saml2MessageBinding.POST) // Add this
.singleSignOnServiceBinding(Saml2MessageBinding.POST)
.wantAuthnRequestsSigned(true)
)
.build();

View File

@@ -18,6 +18,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseBackupInterface;
@@ -50,8 +51,17 @@ public class UserService implements UserServiceInterface {
@Autowired ApplicationProperties applicationProperties;
@Transactional
public void migrateOauth2ToSSO() {
userRepository.findByAuthenticationTypeIgnoreCase("OAUTH2")
.forEach(user -> {
user.setAuthenticationType(AuthenticationType.SSO);
userRepository.save(user);
});
}
// Handle OAUTH2 login and user auto creation.
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
public boolean processSSOPostLogin(String username, boolean autoCreateUser)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) {
return false;
@@ -61,7 +71,7 @@ public class UserService implements UserServiceInterface {
return true;
}
if (autoCreateUser) {
saveUser(username, AuthenticationType.OAUTH2);
saveUser(username, AuthenticationType.SSO);
return true;
}
return false;

View File

@@ -83,7 +83,7 @@ public class CustomOAuth2AuthenticationSuccessHandler
if (userService.usernameExistsIgnoreCase(username)
&& userService.hasPassword(username)
&& !userService.isAuthenticationTypeByUsername(
username, AuthenticationType.OAUTH2)
username, AuthenticationType.SSO)
&& oAuth.getAutoCreateUser()) {
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
return;
@@ -95,7 +95,7 @@ public class CustomOAuth2AuthenticationSuccessHandler
return;
}
if (principal instanceof OAuth2User) {
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
userService.processSSOPostLogin(username, oAuth.getAutoCreateUser());
}
response.sendRedirect(contextPath + "/");
return;

View File

@@ -63,7 +63,7 @@ public class CustomSaml2AuthenticationSuccessHandler
if (userService.usernameExistsIgnoreCase(username)
&& userService.hasPassword(username)
&& !userService.isAuthenticationTypeByUsername(
username, AuthenticationType.OAUTH2)
username, AuthenticationType.SSO)
&& saml2.getAutoCreateUser()) {
response.sendRedirect(
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
@@ -76,7 +76,7 @@ public class CustomSaml2AuthenticationSuccessHandler
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
return;
}
userService.processOAuth2PostLogin(username, saml2.getAutoCreateUser());
userService.processSSOPostLogin(username, saml2.getAutoCreateUser());
response.sendRedirect(contextPath + "/");
return;
} catch (IllegalArgumentException e) {

View File

@@ -244,8 +244,8 @@ public class UserController {
return new RedirectView("/addUsers?messageType=invalidRole", true);
}
if (authType.equalsIgnoreCase(AuthenticationType.OAUTH2.toString())) {
userService.saveUser(username, AuthenticationType.OAUTH2, role);
if (authType.equalsIgnoreCase(AuthenticationType.SSO.toString())) {
userService.saveUser(username, AuthenticationType.SSO, role);
} else {
if (password.isBlank()) {
return new RedirectView("/addUsers?messageType=invalidPassword", true);

View File

@@ -2,5 +2,5 @@ package stirling.software.SPDF.model;
public enum AuthenticationType {
WEB,
OAUTH2
SSO
}

View File

@@ -1,5 +1,6 @@
package stirling.software.SPDF.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -19,4 +20,7 @@ public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Optional<User> findByApiKey(String apiKey);
List<User> findByAuthenticationTypeIgnoreCase(String authenticationType);
}