Compare commits
5 Commits
Frooodle/l
...
saml2-sso-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92c0ddf63b | ||
|
|
7297e9e62d | ||
|
|
f8944fd2a9 | ||
|
|
3fd44fe7af | ||
|
|
4c9c9b5cbe |
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,23 +26,60 @@ 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 {
|
||||||
RelyingPartyRegistration registration =
|
|
||||||
RelyingPartyRegistrations.fromMetadataLocation(
|
// Resource signingCertResource = new ClassPathResource(this.rpSigningCertLocation);
|
||||||
applicationProperties
|
Resource signingCertResource =
|
||||||
.getSecurity()
|
resourceLoader.getResource(
|
||||||
.getSaml()
|
this.applicationProperties
|
||||||
.getIdpMetadataLocation())
|
.getSecurity()
|
||||||
.entityId(applicationProperties.getSecurity().getSaml().getEntityId())
|
.getSaml()
|
||||||
.registrationId(
|
.getCertificateLocation());
|
||||||
applicationProperties.getSecurity().getSaml().getRegistrationId())
|
// Resource signingKeyResource = new ClassPathResource(this.rpSigningKeyLocation);
|
||||||
.build();
|
Resource signingKeyResource =
|
||||||
return new InMemoryRelyingPartyRegistrationRepository(registration);
|
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 =
|
||||||
|
RelyingPartyRegistrations.fromMetadataLocation(
|
||||||
|
applicationProperties
|
||||||
|
.getSecurity()
|
||||||
|
.getSaml()
|
||||||
|
.getIdpMetadataLocation())
|
||||||
|
.entityId(applicationProperties.getSecurity().getSaml().getEntityId())
|
||||||
|
.registrationId(
|
||||||
|
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();
|
||||||
|
return new InMemoryRelyingPartyRegistrationRepository(registration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ public class GeneralUtils {
|
|||||||
}
|
}
|
||||||
settingsYml.save();
|
settingsYml.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String generateMachineFingerprint() {
|
public static String generateMachineFingerprint() {
|
||||||
try {
|
try {
|
||||||
// Get the MAC address
|
// Get the MAC address
|
||||||
@@ -346,7 +346,7 @@ public class GeneralUtils {
|
|||||||
return fingerprint.toString();
|
return fingerprint.toString();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return "GenericID";
|
return "GenericID";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user