Polish saml-extension-federation Configuration

This commit is contained in:
Josh Cummings
2024-11-06 10:55:09 -07:00
parent d058ae66a1
commit 0a7da94e22
4 changed files with 148 additions and 75 deletions

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.io.ApplicationResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.converter.RsaKeyConverters;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("saml2")
public class RelyingPartyMetadata {
private final ResourceLoader resourceLoader = new ApplicationResourceLoader();
private String entityId = "{baseUrl}/saml/metadata";
private String sso = "{baseUrl}/saml/SSO";
private SingleLogout slo = new SingleLogout();
private X509Certificate certificate;
private RSAPrivateKey key;
public RelyingPartyRegistration apply(RelyingPartyRegistration.Builder builder) {
Saml2X509Credential signing = Saml2X509Credential.signing(this.key, this.certificate);
return builder.entityId(this.entityId)
.assertionConsumerServiceLocation(this.sso)
.singleLogoutServiceBinding(this.slo.getBinding())
.singleLogoutServiceLocation(this.slo.getLocation())
.singleLogoutServiceResponseLocation(this.slo.getResponseLocation())
.signingX509Credentials((c) -> c.add(signing))
.build();
}
public void setEntityId(String entityId) {
this.entityId = entityId;
}
public void setSso(String sso) {
this.sso = sso;
}
public void setSlo(SingleLogout slo) {
this.slo = slo;
}
public void setCertificate(String certificate) {
Resource source = this.resourceLoader.getResource(certificate);
try (InputStream in = source.getInputStream()) {
CertificateFactory certificates = CertificateFactory.getInstance("X.509");
this.certificate = (X509Certificate) certificates.generateCertificate(in);
}
catch (CertificateException | IOException ex) {
throw new IllegalArgumentException(ex);
}
}
public void setKey(String key) {
Resource source = this.resourceLoader.getResource(key);
try (InputStream in = source.getInputStream()) {
this.key = RsaKeyConverters.pkcs8().convert(in);
}
catch (IOException ex) {
throw new IllegalArgumentException(ex);
}
}
public static class SingleLogout {
private Saml2MessageBinding binding = Saml2MessageBinding.REDIRECT;
private String location = "{baseUrl}/saml/logout";
private String responseLocation = "{baseUrl}/saml/SingleLogout";
public Saml2MessageBinding getBinding() {
return this.binding;
}
public void setBinding(Saml2MessageBinding binding) {
this.binding = binding;
}
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
public String getResponseLocation() {
if (this.responseLocation == null) {
return this.location;
}
return this.responseLocation;
}
public void setResponseLocation(String responseLocation) {
this.responseLocation = responseLocation;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,26 +16,16 @@
package example;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties;
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Registration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
import org.springframework.security.web.SecurityFilterChain;
@@ -60,32 +50,13 @@ public class SecurityConfiguration {
}
@Bean
InMemoryRelyingPartyRegistrationRepository repository(Saml2RelyingPartyProperties properties,
@Value("classpath:credentials/rp-private.key") RSAPrivateKey key,
@Value("classpath:credentials/rp-certificate.crt") File cert) {
Saml2X509Credential signing = Saml2X509Credential.signing(key, x509Certificate(cert));
Registration registration = properties.getRegistration().values().iterator().next();
return new InMemoryRelyingPartyRegistrationRepository(RelyingPartyRegistrations
.collectionFromMetadataLocation(registration.getAssertingparty().getMetadataUri())
RelyingPartyRegistrationRepository registrations(RelyingPartyMetadata rp,
@Value("${saml2.ap.metadata}") String ap) {
List<RelyingPartyRegistration> registrations = RelyingPartyRegistrations.collectionFromMetadataLocation(ap)
.stream()
.map((builder) -> builder.registrationId(UUID.randomUUID().toString())
.entityId(registration.getEntityId())
.assertionConsumerServiceLocation(registration.getAcs().getLocation())
.singleLogoutServiceBinding(registration.getSinglelogout().getBinding())
.singleLogoutServiceLocation(registration.getSinglelogout().getUrl())
.singleLogoutServiceResponseLocation(registration.getSinglelogout().getResponseUrl())
.signingX509Credentials((credentials) -> credentials.add(signing))
.build())
.collect(Collectors.toList()));
}
X509Certificate x509Certificate(File location) {
try (InputStream source = new FileInputStream(location)) {
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(source);
}
catch (CertificateException | IOException ex) {
throw new IllegalArgumentException(ex);
}
.map(rp::apply)
.toList();
return new InMemoryRelyingPartyRegistrationRepository(registrations);
}
}

View File

@@ -10,15 +10,8 @@ spring:
security:
filter:
dispatcher-types: async, error, request, forward
saml2:
relyingparty:
registration:
metadata:
entity-id: "{baseUrl}/saml/metadata"
singlelogout:
binding: REDIRECT
url: "{baseUrl}/saml/logout"
responseUrl: "{baseUrl}/saml/SingleLogout"
acs:
location: "{baseUrl}/saml/SSO"
assertingparty.metadata-uri: http://idp-one.7f000001.nip.io/simplesaml/saml2/idp/metadata.php
saml2:
certificate: classpath:credentials/rp-certificate.crt
key: classpath:credentials/rp-private.key
ap.metadata: http://idp-one.7f000001.nip.io/simplesaml/saml2/idp/metadata.php

View File

@@ -1,24 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD
VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD
VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX
c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw
aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ
BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa
BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD
DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr
QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62
E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz
2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW
RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ
nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5
cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph
iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5
ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO
nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v
ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu
xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z
V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3
lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk
-----END CERTIFICATE-----