This commit is contained in:
Phillip Webb
2022-04-20 13:48:29 -07:00
parent 71acc90da8
commit 36f1249fc6
9 changed files with 92 additions and 51 deletions

View File

@@ -58,7 +58,6 @@ class DefaultGraphQlSchemaCondition extends SpringBootCondition implements Confi
boolean match = false;
List<ConditionMessage> messages = new ArrayList<>(2);
ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnGraphQlSchema.class);
Binder binder = Binder.get(context.getEnvironment());
GraphQlProperties.Schema schema = binder.bind("spring.graphql.schema", GraphQlProperties.Schema.class)
.orElse(new GraphQlProperties.Schema());

View File

@@ -33,9 +33,10 @@ import org.springframework.util.MimeTypeUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link RSocketGraphQlClient}.
* This auto-configuration creates {@link RSocketGraphQlClient.Builder} prototype beans,
* as the builders are stateful and should not be reused to build client instances with
* different configurations.
* This auto-configuration creates
* {@link org.springframework.graphql.client.RSocketGraphQlClient.Builder
* RSocketGraphQlClient.Builder} prototype beans, as the builders are stateful and should
* not be reused to build client instances with different configurations.
*
* @author Brian Clozel
* @since 2.7.0

View File

@@ -30,6 +30,7 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Moritz Halbritter
* @since 2.2.0
*/
@ConfigurationProperties("spring.security.saml2.relyingparty")

View File

@@ -40,6 +40,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.log.LogMessage;
import org.springframework.security.converter.RsaKeyConverters;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
@@ -49,6 +50,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.Builder;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -58,6 +60,7 @@ import org.springframework.util.StringUtils;
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Moritz Halbritter
*/
@Configuration(proxyBeanMethods = false)
@Conditional(RegistrationConfiguredCondition.class)
@@ -78,12 +81,11 @@ class Saml2RelyingPartyRegistrationConfiguration {
}
private RelyingPartyRegistration asRegistration(String id, Registration properties) {
boolean usingMetadata = StringUtils
.hasText(getFromAssertingParty(properties, id, "metadata-uri", AssertingParty::getMetadataUri));
Builder builder = (usingMetadata) ? RelyingPartyRegistrations
.fromMetadataLocation(
getFromAssertingParty(properties, id, "metadata-uri", AssertingParty::getMetadataUri))
.registrationId(id) : RelyingPartyRegistration.withRegistrationId(id);
AssertingPartyProperties assertingParty = new AssertingPartyProperties(properties, id);
boolean usingMetadata = StringUtils.hasText(assertingParty.getMetadataUri());
Builder builder = (usingMetadata)
? RelyingPartyRegistrations.fromMetadataLocation(assertingParty.getMetadataUri()).registrationId(id)
: RelyingPartyRegistration.withRegistrationId(id);
builder.assertionConsumerServiceLocation(properties.getAcs().getLocation());
builder.assertionConsumerServiceBinding(properties.getAcs().getBinding());
builder.assertingPartyDetails(mapAssertingParty(properties, id, usingMetadata));
@@ -91,8 +93,8 @@ class Saml2RelyingPartyRegistrationConfiguration {
.map(this::asSigningCredential).forEach(credentials::add));
builder.decryptionX509Credentials((credentials) -> properties.getDecryption().getCredentials().stream()
.map(this::asDecryptionCredential).forEach(credentials::add));
builder.assertingPartyDetails((details) -> details.verificationX509Credentials(
(credentials) -> getFromAssertingParty(properties, id, "verification", AssertingParty::getVerification)
builder.assertingPartyDetails(
(details) -> details.verificationX509Credentials((credentials) -> assertingParty.getVerification()
.getCredentials().stream().map(this::asVerificationCredential).forEach(credentials::add)));
builder.entityId(properties.getEntityId());
RelyingPartyRegistration registration = builder.build();
@@ -101,35 +103,15 @@ class Saml2RelyingPartyRegistrationConfiguration {
return registration;
}
@SuppressWarnings("deprecation")
private <T> T getFromAssertingParty(Registration registration, String id, String name,
Function<AssertingParty, T> getter) {
T newValue = getter.apply(registration.getAssertingParty());
if (newValue != null) {
return newValue;
}
T deprecatedValue = getter.apply(registration.getIdentityprovider());
if (deprecatedValue != null) {
logger.warn(String.format(
"Property 'spring.security.saml2.relyingparty.registration.identityprovider.%1$s.%2$s' is deprecated, please use 'spring.security.saml2.relyingparty.registration.asserting-party.%1$s.%2$s' instead",
id, name));
return deprecatedValue;
}
return newValue;
}
private Consumer<AssertingPartyDetails.Builder> mapAssertingParty(Registration registration, String id,
boolean usingMetadata) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
return (details) -> {
map.from(() -> getFromAssertingParty(registration, id, "entity-id", AssertingParty::getEntityId))
.to(details::entityId);
map.from(() -> getFromAssertingParty(registration, id, "singlesignon.binding",
(property) -> property.getSinglesignon().getBinding())).to(details::singleSignOnServiceBinding);
map.from(() -> getFromAssertingParty(registration, id, "singlesignon.url",
(property) -> property.getSinglesignon().getUrl())).to(details::singleSignOnServiceLocation);
map.from(() -> getFromAssertingParty(registration, id, "singlesignon.sign-request",
(property) -> property.getSinglesignon().getSignRequest())).when((ignored) -> !usingMetadata)
AssertingPartyProperties assertingParty = new AssertingPartyProperties(registration, id);
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(assertingParty::getEntityId).to(details::entityId);
map.from(assertingParty::getSingleSignonBinding).to(details::singleSignOnServiceBinding);
map.from(assertingParty::getSingleSignonUrl).to(details::singleSignOnServiceLocation);
map.from(assertingParty::getSingleSignonSignRequest).when((ignored) -> !usingMetadata)
.to(details::wantAuthnRequestsSigned);
};
}
@@ -181,4 +163,61 @@ class Saml2RelyingPartyRegistrationConfiguration {
}
}
/**
* Access to {@link AssertingParty} properties taking into account deprecations.
*/
private static class AssertingPartyProperties {
private final Registration registration;
private final String id;
AssertingPartyProperties(Registration registration, String id) {
this.registration = registration;
this.id = id;
}
String getMetadataUri() {
return get("metadata-uri", AssertingParty::getMetadataUri);
}
Verification getVerification() {
return get("verification", AssertingParty::getVerification);
}
String getEntityId() {
return get("entity-id", AssertingParty::getEntityId);
}
Saml2MessageBinding getSingleSignonBinding() {
return get("singlesignon.binding", (property) -> property.getSinglesignon().getBinding());
}
String getSingleSignonUrl() {
return get("singlesignon.url", (property) -> property.getSinglesignon().getUrl());
}
Boolean getSingleSignonSignRequest() {
return get("singlesignon.sign-request", (property) -> property.getSinglesignon().getSignRequest());
}
@SuppressWarnings("deprecation")
private <T> T get(String name, Function<AssertingParty, T> getter) {
T newValue = getter.apply(this.registration.getAssertingParty());
if (newValue != null) {
return newValue;
}
T deprecatedValue = getter.apply(this.registration.getIdentityprovider());
if (deprecatedValue != null) {
logger.warn(LogMessage.format(
"Property 'spring.security.saml2.relyingparty.registration.identityprovider.%1$s.%2$s' is deprecated, "
+ "please use 'spring.security.saml2.relyingparty.registration.asserting-party.%1$s.%2$s' instead",
this.id, name));
return deprecatedValue;
}
return newValue;
}
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.security.servlet;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -65,7 +63,9 @@ class SpringBootWebSecurityConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
http.authorizeRequests().anyRequest().authenticated();
http.formLogin();
http.httpBasic();
return http.build();
}
@@ -83,7 +83,7 @@ class SpringBootWebSecurityConfiguration {
FilterRegistrationBean<ErrorPageSecurityFilter> errorPageSecurityFilter(ApplicationContext context) {
FilterRegistrationBean<ErrorPageSecurityFilter> registration = new FilterRegistrationBean<>(
new ErrorPageSecurityFilter(context));
registration.setDispatcherTypes(EnumSet.of(DispatcherType.ERROR));
registration.setDispatcherTypes(DispatcherType.ERROR);
return registration;
}

View File

@@ -53,6 +53,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link Saml2RelyingPartyAutoConfiguration}.
*
* @author Madhura Bhave
* @author Moritz Halbritter
*/
class Saml2RelyingPartyAutoConfigurationTests {