Compare commits

...

5 Commits

Author SHA1 Message Date
Dimitrios Kaitantzidis
92c0ddf63b WIP: Try to add saml2 logout with defaults (SamlConfig) 2024-10-07 23:21:36 +03:00
Dimitrios Kaitantzidis
7297e9e62d WIP: Try to add saml2 logout with defaults 2024-10-07 23:20:54 +03:00
Dimitrios Kaitantzidis
f8944fd2a9 WIP: login process works properly 2024-10-07 19:12:56 +03:00
Dimitrios Kaitantzidis
3fd44fe7af WIP: adds certificate properties 2024-10-07 18:46:19 +03:00
Dimitrios Kaitantzidis
4c9c9b5cbe WIP: trying to make it work 2024-10-05 20:52:09 +03:00
6 changed files with 100 additions and 53 deletions

View File

@@ -46,7 +46,6 @@ public class LicenseKeyChecker {
log.info("License key is invalid."); log.info("License key is invalid.");
} }
} }
} }
public void updateLicenseKey(String newKey) throws IOException { public void updateLicenseKey(String newKey) throws IOException {

View File

@@ -1,5 +1,7 @@
package stirling.software.SPDF.config.security; package stirling.software.SPDF.config.security;
import static org.springframework.security.config.Customizer.withDefaults;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -204,8 +206,7 @@ public class SecurityConfiguration {
.equalsIgnoreCase("normal")) { .equalsIgnoreCase("normal")) {
http.saml2Login( http.saml2Login(
saml2 -> { saml2 -> {
saml2.loginPage("/saml2") saml2.relyingPartyRegistrationRepository(
.relyingPartyRegistrationRepository(
relyingPartyRegistrationRepository) relyingPartyRegistrationRepository)
.successHandler( .successHandler(
new CustomSAMLAuthenticationSuccessHandler( new CustomSAMLAuthenticationSuccessHandler(
@@ -215,6 +216,7 @@ public class SecurityConfiguration {
.failureHandler( .failureHandler(
new CustomSAMLAuthenticationFailureHandler()); new CustomSAMLAuthenticationFailureHandler());
}) })
.saml2Logout(withDefaults())
.addFilterBefore( .addFilterBefore(
userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class); userAuthenticationFilter, Saml2WebSsoAuthenticationFilter.class);
} }

View File

@@ -1,10 +1,6 @@
package stirling.software.SPDF.config.security.saml; package stirling.software.SPDF.config.security.saml;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Assertion;
@@ -57,7 +53,12 @@ public class ConvertResponseToAuthentication
return Collections.emptySet(); return Collections.emptySet();
} }
final List<Object> groups = new ArrayList<>(attributes.get(authoritiesAttributeName)); List<Object> groups = new ArrayList<>();
if (attributes.get(authoritiesAttributeName) != null) {
groups = new ArrayList<>(attributes.get(authoritiesAttributeName));
}
return groups.stream() return groups.stream()
.filter(String.class::isInstance) .filter(String.class::isInstance)
.map(String.class::cast) .map(String.class::cast)

View File

@@ -1,15 +1,21 @@
package stirling.software.SPDF.config.security.saml; package stirling.software.SPDF.config.security.saml;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import org.opensaml.security.x509.X509Support;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; import org.springframework.core.io.Resource;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.core.io.ResourceLoader;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.converter.RsaKeyConverters;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations; import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.provider.service.registration.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
@@ -20,13 +26,39 @@ public class SamlConfig {
@Autowired ApplicationProperties applicationProperties; @Autowired ApplicationProperties applicationProperties;
@Autowired ResourceLoader resourceLoader;
@Bean @Bean
@ConditionalOnProperty( @ConditionalOnProperty(
value = "security.saml.enabled", value = "security.saml.enabled",
havingValue = "true", havingValue = "true",
matchIfMissing = false) matchIfMissing = false)
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository()
throws CertificateException { throws CertificateException, IOException {
// Resource signingCertResource = new ClassPathResource(this.rpSigningCertLocation);
Resource signingCertResource =
resourceLoader.getResource(
this.applicationProperties
.getSecurity()
.getSaml()
.getCertificateLocation());
// Resource signingKeyResource = new ClassPathResource(this.rpSigningKeyLocation);
Resource signingKeyResource =
resourceLoader.getResource(
this.applicationProperties.getSecurity().getSaml().getPrivateKeyLocation());
try (InputStream is = signingKeyResource.getInputStream();
InputStream certIS = signingCertResource.getInputStream(); ) {
X509Certificate rpCertificate = X509Support.decodeCertificate(certIS.readAllBytes());
RSAPrivateKey rpKey = RsaKeyConverters.pkcs8().convert(is);
final Saml2X509Credential rpSigningCredentials =
Saml2X509Credential.signing(rpKey, rpCertificate);
X509Certificate apCert =
X509Support.decodeCertificate(
applicationProperties.getSecurity().getSaml().getSigningCertificate());
Saml2X509Credential apCredential = Saml2X509Credential.verification(apCert);
RelyingPartyRegistration registration = RelyingPartyRegistration registration =
RelyingPartyRegistrations.fromMetadataLocation( RelyingPartyRegistrations.fromMetadataLocation(
applicationProperties applicationProperties
@@ -35,8 +67,19 @@ public class SamlConfig {
.getIdpMetadataLocation()) .getIdpMetadataLocation())
.entityId(applicationProperties.getSecurity().getSaml().getEntityId()) .entityId(applicationProperties.getSecurity().getSaml().getEntityId())
.registrationId( .registrationId(
applicationProperties.getSecurity().getSaml().getRegistrationId()) applicationProperties
.getSecurity()
.getSaml()
.getRegistrationId())
.signingX509Credentials(c -> c.add(rpSigningCredentials))
.assertingPartyDetails(
party ->
party.wantAuthnRequestsSigned(true)
.verificationX509Credentials(
c -> c.add(apCredential)))
.singleLogoutServiceLocation("http://localhost:8090/logout/saml2/slo")
.build(); .build();
return new InMemoryRelyingPartyRegistrationRepository(registration); return new InMemoryRelyingPartyRegistrationRepository(registration);
} }
} }
}

View File

@@ -13,9 +13,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
@@ -81,25 +78,30 @@ public class ApplicationProperties {
private String registrationId; private String registrationId;
private String spBaseUrl; private String spBaseUrl;
private String idpMetadataLocation; private String idpMetadataLocation;
private KeyStore keystore; // private KeyStore keystore;
private String privateKeyLocation;
private String certificateLocation;
private String singleLogoutBinding;
private String singleLogoutResponseUri;
private String signingCertificate;
@Data // @Data
public static class KeyStore { // public static class KeyStore {
private String keystoreLocation; // private String keystoreLocation;
private String keystorePassword; // private String keystorePassword;
private String keyAlias; // private String keyAlias;
private String keyPassword; // private String keyPassword;
private String realmCertificateAlias; // private String realmCertificateAlias;
//
public Resource getKeystoreResource() { // public Resource getKeystoreResource() {
if (keystoreLocation.startsWith("classpath:")) { // if (keystoreLocation.startsWith("classpath:")) {
return new ClassPathResource( // return new ClassPathResource(
keystoreLocation.substring("classpath:".length())); // keystoreLocation.substring("classpath:".length()));
} else { // } else {
return new FileSystemResource(keystoreLocation); // return new FileSystemResource(keystoreLocation);
} // }
} // }
} // }
} }
@Data @Data

View File

@@ -5,16 +5,21 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -30,11 +35,6 @@ import com.fathzer.soft.javaluator.DoubleEvaluator;
import io.github.pixee.security.HostValidator; import io.github.pixee.security.HostValidator;
import io.github.pixee.security.Urls; import io.github.pixee.security.Urls;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Enumeration;
public class GeneralUtils { public class GeneralUtils {