Apply SAML2 sign-request even if metadata url is set

Closes gh-33747
pull/37492/head
Moritz Halbritter 1 year ago
parent 4a6dd95b6b
commit 0ed455b058

@ -91,10 +91,10 @@ class Saml2RelyingPartyRegistrationConfiguration {
AssertingPartyProperties assertingParty = new AssertingPartyProperties(properties, id); AssertingPartyProperties assertingParty = new AssertingPartyProperties(properties, id);
boolean usingMetadata = StringUtils.hasText(assertingParty.getMetadataUri()); boolean usingMetadata = StringUtils.hasText(assertingParty.getMetadataUri());
Builder builder = (!usingMetadata) ? RelyingPartyRegistration.withRegistrationId(id) Builder builder = (!usingMetadata) ? RelyingPartyRegistration.withRegistrationId(id)
: createBuilderUsingMetadata(id, assertingParty).registrationId(id); : createBuilderUsingMetadata(assertingParty).registrationId(id);
builder.assertionConsumerServiceLocation(properties.getAcs().getLocation()); builder.assertionConsumerServiceLocation(properties.getAcs().getLocation());
builder.assertionConsumerServiceBinding(properties.getAcs().getBinding()); builder.assertionConsumerServiceBinding(properties.getAcs().getBinding());
builder.assertingPartyDetails(mapAssertingParty(properties, id, usingMetadata)); builder.assertingPartyDetails(mapAssertingParty(properties, id));
builder.signingX509Credentials((credentials) -> properties.getSigning() builder.signingX509Credentials((credentials) -> properties.getSigning()
.getCredentials() .getCredentials()
.stream() .stream()
@ -120,8 +120,7 @@ class Saml2RelyingPartyRegistrationConfiguration {
return registration; return registration;
} }
private RelyingPartyRegistration.Builder createBuilderUsingMetadata(String id, private RelyingPartyRegistration.Builder createBuilderUsingMetadata(AssertingPartyProperties properties) {
AssertingPartyProperties properties) {
String requiredEntityId = properties.getEntityId(); String requiredEntityId = properties.getEntityId();
Collection<Builder> candidates = RelyingPartyRegistrations Collection<Builder> candidates = RelyingPartyRegistrations
.collectionFromMetadataLocation(properties.getMetadataUri()); .collectionFromMetadataLocation(properties.getMetadataUri());
@ -139,17 +138,14 @@ class Saml2RelyingPartyRegistrationConfiguration {
return result[0]; return result[0];
} }
private Consumer<AssertingPartyDetails.Builder> mapAssertingParty(Registration registration, String id, private Consumer<AssertingPartyDetails.Builder> mapAssertingParty(Registration registration, String id) {
boolean usingMetadata) {
return (details) -> { return (details) -> {
AssertingPartyProperties assertingParty = new AssertingPartyProperties(registration, id); AssertingPartyProperties assertingParty = new AssertingPartyProperties(registration, id);
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(assertingParty::getEntityId).to(details::entityId); map.from(assertingParty::getEntityId).to(details::entityId);
map.from(assertingParty::getSingleSignonBinding).to(details::singleSignOnServiceBinding); map.from(assertingParty::getSingleSignonBinding).to(details::singleSignOnServiceBinding);
map.from(assertingParty::getSingleSignonUrl).to(details::singleSignOnServiceLocation); map.from(assertingParty::getSingleSignonUrl).to(details::singleSignOnServiceLocation);
map.from(assertingParty::getSingleSignonSignRequest) map.from(assertingParty::getSingleSignonSignRequest).to(details::wantAuthnRequestsSigned);
.when((ignored) -> !usingMetadata)
.to(details::wantAuthnRequestsSigned);
map.from(assertingParty.getSinglelogoutUrl()).to(details::singleLogoutServiceLocation); map.from(assertingParty.getSinglelogoutUrl()).to(details::singleLogoutServiceLocation);
map.from(assertingParty.getSinglelogoutResponseUrl()).to(details::singleLogoutServiceResponseLocation); map.from(assertingParty.getSinglelogoutResponseUrl()).to(details::singleLogoutServiceResponseLocation);
map.from(assertingParty.getSinglelogoutBinding()).to(details::singleLogoutServiceBinding); map.from(assertingParty.getSinglelogoutBinding()).to(details::singleLogoutServiceBinding);

@ -16,7 +16,6 @@
package org.springframework.boot.autoconfigure.security.saml2; package org.springframework.boot.autoconfigure.security.saml2;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
@ -416,7 +415,26 @@ class Saml2RelyingPartyAutoConfigurationTests {
testMultipleProviders("https://idp2.example.com/idp/shibboleth", "https://idp2.example.com/idp/shibboleth"); testMultipleProviders("https://idp2.example.com/idp/shibboleth", "https://idp2.example.com/idp/shibboleth");
} }
private void testMultipleProviders(String specifiedEntityId, String expected) throws IOException, Exception { @Test
void signRequestShouldApplyIfMetadataUriIsSet() throws Exception {
try (MockWebServer server = new MockWebServer()) {
server.start();
String metadataUrl = server.url("").toString();
setupMockResponse(server, new ClassPathResource("saml/idp-metadata"));
this.contextRunner.withPropertyValues(PREFIX + ".foo.assertingparty.metadata-uri=" + metadataUrl,
PREFIX + ".foo.assertingparty.singlesignon.sign-request=true",
PREFIX + ".foo.signing.credentials[0].private-key-location=classpath:org/springframework/boot/autoconfigure/security/saml2/rsa.key",
PREFIX + ".foo.signing.credentials[0].certificate-location=classpath:org/springframework/boot/autoconfigure/security/saml2/rsa.crt")
.run((context) -> {
RelyingPartyRegistrationRepository repository = context
.getBean(RelyingPartyRegistrationRepository.class);
RelyingPartyRegistration registration = repository.findByRegistrationId("foo");
assertThat(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isTrue();
});
}
}
private void testMultipleProviders(String specifiedEntityId, String expected) throws Exception {
try (MockWebServer server = new MockWebServer()) { try (MockWebServer server = new MockWebServer()) {
server.start(); server.start();
String metadataUrl = server.url("").toString(); String metadataUrl = server.url("").toString();

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID1zCCAr+gAwIBAgIUCzQeKBMTO0iHVW3iKmZC41haqCowDQYJKoZIhvcNAQEL
BQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI
Q2l0eU5hbWUxFDASBgNVBAoMC0NvbXBhbnlOYW1lMRswGQYDVQQLDBJDb21wYW55
U2VjdGlvbk5hbWUxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMzA5MjAwODI5MDNa
Fw0zMzA5MTcwODI5MDNaMHsxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5h
bWUxETAPBgNVBAcMCENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkG
A1UECwwSQ29tcGFueVNlY3Rpb25OYW1lMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUfi4aaCotJZX6OSDjv6fxCCfc
ihSs91Z/mmN+yc1fsxVSs53SIbqUuo+Wzhv34kp8I/r03P9LWVTkFPbeDxAl75Oa
PGggxK55US0Zfy9Hj1BwWIKV3330N61emID1GDEtFKL4yJbJdreQXnIXTBL2o76V
nuV/tYozyZnb07IQ1WhUm5WDxgzM0yFudMynTczCBeZHfvharDtB8PFFhCZXW2/9
TZVVfW4oOML8EAX3hvnvYBlFl/foxXekZSwq/odOkmWCZavT2+0sburHUlOnPGUh
Qj4tHwpMRczp7VX4ptV1D2UrxsK/2B+s9FK2QSLKQ9JzAYJ6WxQjHcvET9jvAgMB
AAGjUzBRMB0GA1UdDgQWBBQjDr/1E/01pfLPD8uWF7gbaYL0TTAfBgNVHSMEGDAW
gBQjDr/1E/01pfLPD8uWF7gbaYL0TTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQAGjUuec0+0XNMCRDKZslbImdCAVsKsEWk6NpnUViDFAxL+KQuC
NW131UeHb9SCzMqRwrY4QI3nAwJQCmilL/hFM3ss4acn3WHu1yci/iKPUKeL1ec5
kCFUmqX1NpTiVaytZ/9TKEr69SMVqNfQiuW5U1bIIYTqK8xo46WpM6YNNHO3eJK6
NH0MW79Wx5ryi4i4C6afqYbVbx7tqcmy8CFeNxgZ0bFQ87SiwYXIj77b6sVYbu32
doykBQgSHLcagWASPQ73m73CWUgo+7+EqSKIQqORbgmTLPmOUh99gFIx7jmjTyHm
NBszx1ZVWuIv3mWmp626Kncyc+LLM9tvgymx
-----END CERTIFICATE-----

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUfi4aaCotJZX6
OSDjv6fxCCfcihSs91Z/mmN+yc1fsxVSs53SIbqUuo+Wzhv34kp8I/r03P9LWVTk
FPbeDxAl75OaPGggxK55US0Zfy9Hj1BwWIKV3330N61emID1GDEtFKL4yJbJdreQ
XnIXTBL2o76VnuV/tYozyZnb07IQ1WhUm5WDxgzM0yFudMynTczCBeZHfvharDtB
8PFFhCZXW2/9TZVVfW4oOML8EAX3hvnvYBlFl/foxXekZSwq/odOkmWCZavT2+0s
burHUlOnPGUhQj4tHwpMRczp7VX4ptV1D2UrxsK/2B+s9FK2QSLKQ9JzAYJ6WxQj
HcvET9jvAgMBAAECggEADdeRuZml1F65mDJm1enduaH+NWvEm1yEr3ecr0fbujYI
bQ89+CVx/znvRvPH4aFwQwmgUZl12JrfS05MTectoPMBf/obDwtmPDPmsV2rdEi9
2jEB11vW23T8X7L6hOdzCKHqrd8kkhzK1LuPnhHlaFipU8YlOBOuMYpv8eB78y79
Qkd5/ZEygFhqVGz96R7nT/xS21aPC7OPhicAauLLuguF4caCNhwkjLi3bizLemUn
4i41q69drg7G8WX6BTxzem5FupKfI8rn2EkOjO/biVRknzGxAdqkM8SDHWkqeOuY
8QVhc1kZsMkB0BGPlDPStUwEHSfUiND4GJTcngc++QKBgQD2lyeW3PoPjQ1qzjN4
V/0XE77zpcPE5dW7chLtiWRY1dqk2uOJ32iOtxuqk9Q/YMSZyPJlTkfI5JePuC/B
MB+QXzXuWN03Vn0ZrOpQlxcdA4A1o10NT1nEw8kZlf4+LyUk8GpMGUhjnxFZpZbf
5S3fy0/2V8wGvOmXR65c8m6ASQKBgQDcmfCV5npu1HrtO8jmU9gBIhniNjB4IWue
TSRt3ANDQaVBqsVaIMe/mUEQrZ6MdikMeA4bobOA6bUYwOiq8JGWSenAzGL22TbA
W51q6A8hgDCuH1JnoagqUIbr61kwEVcfbRHEFpuxLURsjoDg/xBtwO96SxWPh5Wr
+f1q8t5/dwKBgGWc+AVk3e6Wk1bVzcPjjjl6O4+vWTLD+wUZBs+3dBBfX4/bWzQv
Sai1r8Lk0+uh9qHgenJghZg1CneA0LztFbSqZ1DmcZIiI7720D+RY0bjcGup++hG
MJmyjCXs9y2sw8OrBkKBkKDspXupjriIehTkdPjwSPTl1+Qs9575j6txAoGAT8n+
ErnCHsQLkjLFf0lkH0TOR9uBvHGaEy+jtXiWVYUw2IeDyg2BMfOkbPvfFL7IKhJi
R+w8mKvvLHzZqrpIbitduLY0NURrYTfBwCEfF+bdtJzvmTwHLwbhRgNhxtj+wgcZ
HetvdK4CyaDhTH/02T2nYHw32CoaIJHS7xPZFhECgYEAv7xRawjlrC4V0BLjP3Ej
pk8BbsRABxN1CrS6nJK+So4u2gKQDsL3WA0oJTS8v8AD5LvQUNr1d57FVlq9lwCd
u623eOIuluCUZBVy1iYdkRXWz9pg5bCidCgEYUpF3SqpsuFou0XFzDD773UVQFVw
VYriYasPwmzS2y2P7PKFzJs=
-----END PRIVATE KEY-----
Loading…
Cancel
Save