Open chriswhite199 opened 4 years ago
One solution i've found is to use AutoConfiguration vs @EnableSAMLSSO
.
Taking the first unit test from my previous post, if you comment out the @EnableSAMLSSO
and instead add a META-INF/spring.factories
file with the following contents, the test now passes:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.ulisesbocchio.spring.boot.security.saml.configuration.SAMLServiceProviderSecurityConfiguration
This does mean that you can't easily enable / disable without changing this file, but i'm assuming that a simple wrapper AutoConfiguration class (outside the scanning classpath) with a @ConditionalOnProperty should work.
So taking this to its logical conclusion:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.ulisesbocchio.spring.boot.security.saml.configurer.WebSecurityConfigurerAdapterTest.SamlAutoConfiguration
package com.github.ulisesbocchio.spring.boot.security.saml.configurer;
import com.github.ulisesbocchio.spring.boot.security.saml.annotation.EnableSAMLSSO;
import com.github.ulisesbocchio.spring.boot.security.saml.bean.SAMLConfigurerBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = {
WebSecurityConfigurerAdapterTest.MyWebSecurityConfigurerAdapter.class
},
properties = {
"spring.security.saml.enabled=true"
})
public class WebSecurityConfigurerAdapterTest {
@SpringBootApplication
public static class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Bean
SAMLConfigurerBean saml() {
return new SAMLConfigurerBean();
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.disable()
.csrf()
.disable()
.anonymous()
.and()
.apply(saml())
.and()
.authorizeRequests()
.requestMatchers(saml().endpointsMatcher())
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
@ConditionalOnProperty(value = "spring.security.saml.enabled", havingValue = "true")
@EnableSAMLSSO
public static class SamlAutoConfiguration {
}
@Test
public void contextLoads() throws Exception {
}
}
Hi i am also facing the same problem
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'saml' defined in com.spring.MainApplication: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=mainApplication; factoryMethodName=saml; initMethodName=null; destroyMethodName=(inferred); defined in com.spring.MainApplication] for bean 'saml': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.github.ulisesbocchio.spring.boot.security.saml.configuration.SAMLServiceProviderSecurityConfiguration$SAMLWebSecurityConfigurer; factoryMethodName=saml; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/github/ulisesbocchio/spring/boot/security/saml/configuration/SAMLServiceProviderSecurityConfiguration$SAMLWebSecurityConfigurer.class]] bound.
at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:927) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:287) ~[spring-context-5.2.4.RELEASE
If i use ServiceProviderConfigurerAdapter method, the Configurer parameter does not seems to be set.
The project i working on have an existing WebSecurityConfigurerAdapter, is there anyway around this?
is there any advice for configuration ordering when trying to define you own WebSecurityConfigurerAdapter, as per the docs?
I get the following error when trying to create a WebSecurityConfigurerAdapter:
Here's a sample unit test that replicates
To work around this, if you move the @EnableSAMLSSO to another configuration class, that is lexicographically greater than the config for the adapter, it works:
No amount of using [@]Order, implements Ordered or AutoConfigureXXX seems to resolve this without naming the second class accordingly.
I'm thinking this would be resolved by explicit AutoConfiguration of SAMLServiceProviderSecurityConfiguration in META-INF/spring.factories, as the ConditionalOnMissingBeans would be invoked after any other user defined [@]Configuration classes