ulisesbocchio / spring-boot-security-saml

spring-security-saml integration with Spring Boot
MIT License
157 stars 72 forks source link

@EnableSAMLSSO on @Configuation #72

Closed chriswhite199 closed 5 years ago

chriswhite199 commented 5 years ago

I'm having issues trying to toggle @EnableSAMLSSO on a configuration (for example trying to launch the boot application with a profile).

The docs note:

Add the @EnableSAMLSSO annotation to your Spring Boot Application on any @Configuration class:

So i have the following, trying to only configure when a property is set:

@Configuration
@EnableSAMLSSO
@ConditionalOnProperty(value="security.saml.enable", matchIfMissing=true, havingValue="true")
public class SAMLSecurityConfig extends WebSecurityConfigurerAdapter {
   // as per the docs: https://github.com/ulisesbocchio/spring-boot-security-saml#using-websecurityconfigureradapter
}

And this works fine to disable saml when the property is set to false. But when the property is not set, i get the following error:

Error creating bean with name 'springSecurityFilterChain' ... This object has already been built.

Is there something i'm obviously doing wrong? I don't see an example of @EnableSAMLSSO being set on anything other than the Application class in the samples repository.

chriswhite199 commented 5 years ago

You can easily reproduce this by moving the @ENableSAMLSSO annotation in the okta2 sample project from the OktaSSODemoApplication2 class to the MyServiceProviderConfig:

@Configuration
@EnableSAMLSSO
public static class MyServiceProviderConfig extends WebSecurityConfigurerAdapter {
2018-10-11 16:34:31.159  INFO 37322 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@58978fec, org.springframework.security.web.context.SecurityContextPersistenceFilter@3aa1ed82, org.springframework.security.web.header.HeaderWriterFilter@1f8cd5c8, org.springframework.security.saml.metadata.MetadataGeneratorFilter@5599b7df, org.springframework.security.saml.metadata.MetadataDisplayFilter@50c023a9, org.springframework.security.saml.SAMLEntryPoint@30e5fceb, org.springframework.security.saml.SAMLProcessingFilter@54e9fdf4, org.springframework.security.saml.SAMLWebSSOHoKProcessingFilter@4c568ff9, org.springframework.security.saml.SAMLLogoutProcessingFilter@1d5a30b1, org.springframework.security.saml.SAMLDiscovery@2478555, org.springframework.security.saml.SAMLLogoutFilter@19daceb4, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2776f53d, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@49ff86b7, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@610ba331, org.springframework.security.web.session.SessionManagementFilter@48fc33c1, org.springframework.security.web.access.ExceptionTranslationFilter@68ea103d, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@d15fbc2]
2018-10-11 16:34:31.164  WARN 37322 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built

...

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1247)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265)
    at com.github.ulisesbocchio.demo.OktaSSODemoApplication2.main(OktaSSODemoApplication2.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:497)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)
    ... 26 common frames omitted
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:44)
    at com.github.ulisesbocchio.spring.boot.security.saml.bean.SAMLConfigurerBean.init(SAMLConfigurerBean.java:225)
    at com.github.ulisesbocchio.spring.boot.security.saml.bean.SAMLConfigurerBean.init(SAMLConfigurerBean.java:137)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:371)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:325)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41)
    at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:292)
    at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:79)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:334)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:104)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$c56f0d15.CGLIB$springSecurityFilterChain$2(<generated>)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$c56f0d15$$FastClassBySpringCGLIB$$5040c525.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:365)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$c56f0d15.springSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 27 common frames omitted
bduchesneau commented 5 years ago

Using Spring Boot 2 and spring-boot-security-saml 1.16

I'm also trying to do the same thing but with separate spring profiles. If I move the @EnableSAMLSSO annotation anywhere besides the @SpringBootApplication class I get the error:

WARN - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built INFO - Unregistering JMX-exposed beans on shutdown INFO - Shutting down Quartz Scheduler INFO - Scheduler scheduler_$_NONCLUSTERED shutting down. INFO - Scheduler scheduler$_NONCLUSTERED paused. INFO - Scheduler scheduler$_NON_CLUSTERED shutdown complete. INFO - Shutting down ExecutorService 'threadPoolTaskExecutor' INFO - Closed connection [connectionId{localValue:2, serverValue:1132383}] to vpmongo-dev.valpak.com:27017 because the pool has been closed. INFO - Stopping service [Tomcat]

chriswhite199 commented 5 years ago

See https://github.com/ulisesbocchio/spring-boot-security-saml-samples/issues/3#issuecomment-269235667 - this approach worked for me (using a second configuration class and importing it directly from the main application class)

bduchesneau commented 5 years ago

Thanks. The first option worked for me in combination with @Profile("sso")

On Oct 26, 2018, at 12:36 AM, Chris White notifications@github.com wrote:

See ulisesbocchio/spring-boot-security-saml-samples#3 (comment) https://github.com/ulisesbocchio/spring-boot-security-saml-samples/issues/3#issuecomment-269235667 - this approach worked for me (using a second configuration class and importing it directly from the main application class)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ulisesbocchio/spring-boot-security-saml/issues/72#issuecomment-433283789, or mute the thread https://github.com/notifications/unsubscribe-auth/AJ30x8vA4HQAipuJK_u-2yJbidquXEUKks5uopFRgaJpZM4XYiz7.

ulisesbocchio commented 5 years ago

glad you guys figured it out. This are problems with the way Spring Security loads. My guess is that you guys may have another auth mechanism besides samlsso bootstrapping. Maybe basic auth? Anyway, closing since you guys are good.