From 6c541468f69c4c8c4d027c162c04f6a2971397b7 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 25 Mar 2015 20:54:45 -0500 Subject: [PATCH] SEC-2913: Post Process default session fixation AuthenticationStrategy Before the default session fixation AuthenticationStrategy used a NullEventPublisher when using the Java Configuration. This was due to the fact that it is not exposed as a Bean and is not post processed. We now post process the default session fixation AuthenticationStrategy which initializes the EventPublisher properly. --- .../SessionManagementConfigurer.java | 6 +- .../NamespaceSessionManagementTests.groovy | 268 +++++++------ .../SessionManagementConfigurerTests.groovy | 367 +++++++++--------- 3 files changed, 340 insertions(+), 301 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index a711ac7f81..945af6b0b8 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -91,7 +91,8 @@ import org.springframework.util.Assert; */ public final class SessionManagementConfigurer> extends AbstractHttpConfigurer, H> { - private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy(); + private final SessionAuthenticationStrategy DEFAULT_SESSION_FIXATION_STRATEGY = createDefaultSessionFixationProtectionStrategy(); + private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = DEFAULT_SESSION_FIXATION_STRATEGY; private SessionAuthenticationStrategy sessionAuthenticationStrategy; private InvalidSessionStrategy invalidSessionStrategy; private List sessionAuthenticationStrategies = new ArrayList(); @@ -475,6 +476,9 @@ public final class SessionManagementConfigurer> return sessionAuthenticationStrategy; } List delegateStrategies = sessionAuthenticationStrategies; + if(DEFAULT_SESSION_FIXATION_STRATEGY == sessionFixationAuthenticationStrategy) { + sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy); + } if (isConcurrentSessionControlEnabled()) { SessionRegistry sessionRegistry = getSessionRegistry(http); ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy( diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy index e46a30a224..0fb4d1ccd6 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy @@ -15,19 +15,19 @@ */ package org.springframework.security.config.annotation.web.configurers -import org.springframework.context.annotation.Configuration +import org.springframework.context.ApplicationListener +import org.springframework.context.annotation.Bean +import org.springframework.mock.web.MockHttpSession +import org.springframework.security.authentication.TestingAuthenticationToken import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.ObjectPostProcessor -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.core.session.SessionRegistry -import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; -import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; +import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy +import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy -import org.springframework.security.web.context.SecurityContextPersistenceFilter -import org.springframework.security.web.context.SecurityContextRepository import org.springframework.security.web.session.ConcurrentSessionFilter import org.springframework.security.web.session.SessionManagementFilter @@ -37,124 +37,156 @@ import org.springframework.security.web.session.SessionManagementFilter */ class NamespaceSessionManagementTests extends BaseSpringSpec { - def "http/session-management"() { - when: - loadConfig(SessionManagementConfig) - then: - findSessionAuthenticationStrategy(SessionFixationProtectionStrategy) - } + def "http/session-management"() { + when: + loadConfig(SessionManagementConfig) + then: + findSessionAuthenticationStrategy(SessionFixationProtectionStrategy) + } - @EnableWebSecurity - static class SessionManagementConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - // enabled by default - } - } + @EnableWebSecurity + static class SessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + // enabled by default + } + } - def "http/session-management custom"() { - setup: - CustomSessionManagementConfig.SR = Mock(SessionRegistry) - when: - loadConfig(CustomSessionManagementConfig) - def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0] - then: - findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session" - findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error" - concurrentStrategy.maximumSessions == 1 - concurrentStrategy.exceptionIfMaximumExceeded - concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR - findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session" - } + def "http/session-management custom"() { + setup: + CustomSessionManagementConfig.SR = Mock(SessionRegistry) + when: + loadConfig(CustomSessionManagementConfig) + def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0] + then: + findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session" + findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error" + concurrentStrategy.maximumSessions == 1 + concurrentStrategy.exceptionIfMaximumExceeded + concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR + findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session" + } - @EnableWebSecurity - static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter { - static SessionRegistry SR - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - .invalidSessionUrl("/invalid-session") // session-management@invalid-session-url - .sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url - .maximumSessions(1) // session-management/concurrency-control@max-sessions - .maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded - .expiredUrl("/expired-session") // session-management/concurrency-control@expired-url - .sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref - } - } + @EnableWebSecurity + static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter { + static SessionRegistry SR + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + .invalidSessionUrl("/invalid-session") // session-management@invalid-session-url + .sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url + .maximumSessions(1) // session-management/concurrency-control@max-sessions + .maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded + .expiredUrl("/expired-session") // session-management/concurrency-control@expired-url + .sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref + } + } - def "http/session-management refs"() { - setup: - RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy) - when: - loadConfig(RefsSessionManagementConfig) - then: - findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it == RefsSessionManagementConfig.SAS } - } + def "http/session-management refs"() { + setup: + RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy) + when: + loadConfig(RefsSessionManagementConfig) + then: + findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it == RefsSessionManagementConfig.SAS } + } - @EnableWebSecurity - static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter { - static SessionAuthenticationStrategy SAS - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - .sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref - } - } + @EnableWebSecurity + static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter { + static SessionAuthenticationStrategy SAS + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + .sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref + } + } - def "http/session-management@session-fixation-protection=none"() { - when: - loadConfig(SFPNoneSessionManagementConfig) - then: - findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof NullAuthenticatedSessionStrategy } - } + def "http/session-management@session-fixation-protection=none"() { + when: + loadConfig(SFPNoneSessionManagementConfig) + then: + findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof NullAuthenticatedSessionStrategy } + } - @EnableWebSecurity - static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - .sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()) - } - } + @EnableWebSecurity + static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + .sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()) + } + } - def "http/session-management@session-fixation-protection=migrateSession (default)"() { - when: - loadConfig(SFPMigrateSessionManagementConfig) - then: - findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes - } + def "http/session-management@session-fixation-protection=migrateSession (default)"() { + when: + loadConfig(SFPMigrateSessionManagementConfig) + then: + findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes + } - @EnableWebSecurity - static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - } - } + @EnableWebSecurity + static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + } + } - def "http/session-management@session-fixation-protection=newSession"() { - when: - loadConfig(SFPNewSessionSessionManagementConfig) - then: - !findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes - } + def "http/session-management@session-fixation-protection=changeSessionId"() { + setup: + loadConfig(SFPPostProcessedConfig) + when: + findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).onSessionChange("id", new MockHttpSession(), new TestingAuthenticationToken("u","p","ROLE_USER")) + then: + context.getBean(MockEventListener).events + } - def findSessionAuthenticationStrategy(def c) { - findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it.class.isAssignableFrom(c) } - } + @EnableWebSecurity + static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + } - @EnableWebSecurity - static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - .sessionFixation() - .newSession() - } - } + @Bean + public MockEventListener eventListener() { + new MockEventListener() + } + } + + def "http/session-management@session-fixation-protection=newSession"() { + when: + loadConfig(SFPNewSessionSessionManagementConfig) + then: + !findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes + } + + def findSessionAuthenticationStrategy(def c) { + findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it.class.isAssignableFrom(c) } + } + + @EnableWebSecurity + static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + .sessionFixation() + .newSession() + } + } + + static class MockEventListener implements ApplicationListener { + List events = [] + + public void onApplicationEvent(SessionFixationProtectionEvent event) { + events.add(event) + } + + } } diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy index 905ff5be41..e44279ef31 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy @@ -34,6 +34,7 @@ import org.springframework.security.web.access.ExceptionTranslationFilter import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy +import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy; import org.springframework.security.web.context.NullSecurityContextRepository import org.springframework.security.web.context.SecurityContextPersistenceFilter import org.springframework.security.web.context.SecurityContextRepository @@ -48,205 +49,207 @@ import org.springframework.security.web.session.SessionManagementFilter */ class SessionManagementConfigurerTests extends BaseSpringSpec { - def "sessionManagement does not override explicit RequestCache"() { - setup: - SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache) - when: - loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig) - then: - findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE - } + def "sessionManagement does not override explicit RequestCache"() { + setup: + SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache) + when: + loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig) + then: + findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE + } - @EnableWebSecurity - static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter { - static RequestCache REQUEST_CACHE + @EnableWebSecurity + static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter { + static RequestCache REQUEST_CACHE - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .requestCache() - .requestCache(REQUEST_CACHE) - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - } + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .requestCache() + .requestCache(REQUEST_CACHE) + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + } - } + } - def "sessionManagement does not override explict SecurityContextRepository"() { - setup: - SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository) - when: - loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig) - then: - findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO - } + def "sessionManagement does not override explict SecurityContextRepository"() { + setup: + SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository) + when: + loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig) + then: + findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO + } - @EnableWebSecurity - static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter { - static SecurityContextRepository SECURITY_CONTEXT_REPO + @EnableWebSecurity + static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter { + static SecurityContextRepository SECURITY_CONTEXT_REPO - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .securityContext() - .securityContextRepository(SECURITY_CONTEXT_REPO) - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - } + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .securityContext() + .securityContextRepository(SECURITY_CONTEXT_REPO) + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + } - } + } - def "invoke sessionManagement twice does not override"() { - when: - loadConfig(InvokeTwiceDoesNotOverride) - then: - findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository - } + def "invoke sessionManagement twice does not override"() { + when: + loadConfig(InvokeTwiceDoesNotOverride) + then: + findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository + } - @EnableWebSecurity - static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .sessionManagement() - } + @EnableWebSecurity + static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .sessionManagement() + } - } + } - def 'SEC-2137: disable session fixation and enable concurrency control'() { - setup: "context where session fixation is disabled and concurrency control is enabled" - loadConfig(DisableSessionFixationEnableConcurrencyControlConfig) - String originalSessionId = request.session.id - String credentials = "user:password" - request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64()) - when: "authenticate" - springSecurityFilterChain.doFilter(request, response, new MockFilterChain()) - then: "session invalidate is not called" - request.session.id == originalSessionId - } + def 'SEC-2137: disable session fixation and enable concurrency control'() { + setup: "context where session fixation is disabled and concurrency control is enabled" + loadConfig(DisableSessionFixationEnableConcurrencyControlConfig) + String originalSessionId = request.session.id + String credentials = "user:password" + request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64()) + when: "authenticate" + springSecurityFilterChain.doFilter(request, response, new MockFilterChain()) + then: "session invalidate is not called" + request.session.id == originalSessionId + } - @EnableWebSecurity - static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter { - @Override - public void configure(HttpSecurity http) { - http - .httpBasic() - .and() - .sessionManagement() - .sessionFixation().none() - .maximumSessions(1) - } - @Override - protected void configure(AuthenticationManagerBuilder auth) { - auth - .inMemoryAuthentication() - .withUser("user").password("password").roles("USER") - } - } + @EnableWebSecurity + static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter { + @Override + public void configure(HttpSecurity http) { + http + .httpBasic() + .and() + .sessionManagement() + .sessionFixation().none() + .maximumSessions(1) + } + @Override + protected void configure(AuthenticationManagerBuilder auth) { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER") + } + } - def 'session fixation and enable concurrency control'() { - setup: "context where session fixation is disabled and concurrency control is enabled" - loadConfig(ConcurrencyControlConfig) - def authenticatedSession - when: "authenticate successfully" - request.servletPath = "/login" - request.method = "POST" - request.setParameter("username", "user"); - request.setParameter("password","password") - springSecurityFilterChain.doFilter(request, response, chain) - authenticatedSession = request.session - then: "authentication is sucessful" - response.status == HttpServletResponse.SC_MOVED_TEMPORARILY - response.redirectedUrl == "/" - when: "authenticate with the same user" - super.setup() - request.servletPath = "/login" - request.method = "POST" - request.setParameter("username", "user"); - request.setParameter("password","password") - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_MOVED_TEMPORARILY - response.redirectedUrl == '/login?error' - when: 'SEC-2574: When Session Expires and authentication attempted' - context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession)) - super.setup() - request.servletPath = "/login" - request.method = "POST" - request.setParameter("username", "user"); - request.setParameter("password","password") - springSecurityFilterChain.doFilter(request, response, chain) - then: "authentication is successful" - response.status == HttpServletResponse.SC_MOVED_TEMPORARILY - response.redirectedUrl == "/" - } + def 'session fixation and enable concurrency control'() { + setup: "context where session fixation is disabled and concurrency control is enabled" + loadConfig(ConcurrencyControlConfig) + def authenticatedSession + when: "authenticate successfully" + request.servletPath = "/login" + request.method = "POST" + request.setParameter("username", "user"); + request.setParameter("password","password") + springSecurityFilterChain.doFilter(request, response, chain) + authenticatedSession = request.session + then: "authentication is sucessful" + response.status == HttpServletResponse.SC_MOVED_TEMPORARILY + response.redirectedUrl == "/" + when: "authenticate with the same user" + super.setup() + request.servletPath = "/login" + request.method = "POST" + request.setParameter("username", "user"); + request.setParameter("password","password") + springSecurityFilterChain.doFilter(request, response, chain) + then: + response.status == HttpServletResponse.SC_MOVED_TEMPORARILY + response.redirectedUrl == '/login?error' + when: 'SEC-2574: When Session Expires and authentication attempted' + context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession)) + super.setup() + request.servletPath = "/login" + request.method = "POST" + request.setParameter("username", "user"); + request.setParameter("password","password") + springSecurityFilterChain.doFilter(request, response, chain) + then: "authentication is successful" + response.status == HttpServletResponse.SC_MOVED_TEMPORARILY + response.redirectedUrl == "/" + } - @EnableWebSecurity - static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter { - @Override - public void configure(HttpSecurity http) { - http - .formLogin() - .and() - .sessionManagement() - .maximumSessions(1) - .maxSessionsPreventsLogin(true) - } - @Override - protected void configure(AuthenticationManagerBuilder auth) { - auth - .inMemoryAuthentication() - .withUser("user").password("password").roles("USER") - } - } + @EnableWebSecurity + static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter { + @Override + public void configure(HttpSecurity http) { + http + .formLogin() + .and() + .sessionManagement() + .maximumSessions(1) + .maxSessionsPreventsLogin(true) + } + @Override + protected void configure(AuthenticationManagerBuilder auth) { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER") + } + } - def "sessionManagement ObjectPostProcessor"() { - setup: - AnyObjectPostProcessor opp = Mock() - HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:]) - when: - http - .sessionManagement() - .maximumSessions(1) - .and() - .and() - .build() + def "sessionManagement ObjectPostProcessor"() { + setup: + AnyObjectPostProcessor opp = Mock() + HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:]) + when: + http + .sessionManagement() + .maximumSessions(1) + .and() + .and() + .build() - then: "SessionManagementFilter is registered with ObjectPostProcessor" - 1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o} - and: "ConcurrentSessionFilter is registered with ObjectPostProcessor" - 1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o} - and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor" - 1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o} - and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor" - 1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o} - and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor" - 1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o} - } + then: "SessionManagementFilter is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o} + and: "ConcurrentSessionFilter is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o} + and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o} + and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o} + and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o} + and: "SessionFixationProtectionStrategy is registered with ObjectPostProcessor" + 1 * opp.postProcess(_ as SessionFixationProtectionStrategy) >> {SessionFixationProtectionStrategy o -> o} + } - def "use sharedObject trustResolver"() { - setup: - SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver) - when: - loadConfig(SharedTrustResolverConfig) - then: - findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR - findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR - } + def "use sharedObject trustResolver"() { + setup: + SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver) + when: + loadConfig(SharedTrustResolverConfig) + then: + findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR + findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR + } - @EnableWebSecurity - static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { - static AuthenticationTrustResolver TR + @EnableWebSecurity + static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .setSharedObject(AuthenticationTrustResolver, TR) - } - } + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .setSharedObject(AuthenticationTrustResolver, TR) + } + } }