Summary

When using session creation policy = STATELESS and form login, when authentication fails, the default failure handler creates a session but that is unexpected.

Actual Behavior

SimpleUrlAuthenticationFailureHandler is the default failure handler based on the below configuration. It has allowSessionCreation = true. That causes it to create a session even when session creation policy is stateless: as evidenced by seeing a JSESSIONID in the response from authentication failure.

Expected Behavior

SimpleUrlAuthenticationFailureHandler should obey session creation policy.

There is a workaround because that handler has setter setAllowSessionCreation, so you can manually configure it. But, would it be desirable for it to follow session creation policy instead?

If you implement the workaround, then you no longer see a JSESSIONID in the response from authentication failure.

Configuration

protected void configure(HttpSecurity httpSecurity) throws Exception
{
    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    httpSecurity.formLogin()
       .authenticationDetailsSource(createMyAuthenticationDetailsSource())
       .successHandler(createMyStatelessAuthenticationSuccessHandler());
}

Version

Spring Security 4.1.3 (Spring Boot 1.4.2)

Sample

Example workaround if you wire SimpleUrlAuthenticationFailureHandler and setAllowSessionCreation(false):

@Bean(autowire = Autowire.BY_TYPE)
public SimpleUrlAuthenticationFailureHandler createFailureHandler()
{
    SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
    failureHandler.setAllowSessionCreation(false);
    return failureHandler;
}

protected void configure(HttpSecurity httpSecurity) throws Exception
{
    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    httpSecurity.formLogin()
       .authenticationDetailsSource(createMyAuthenticationDetailsSource())
       .successHandler(createMyStatelessAuthenticationSuccessHandler())
       .failureHandler(createFailureHandler());
}

Comment From: inisson

I have seen this as well..

Comment From: alex-exelweb

This happens because of Spring standard implementation of HttpSessionRequestCache: private boolean createSessionAllowed = true; And

if (createSessionAllowed || request.getSession(false) != null) {
        // Store the HTTP request itself. Used by
        // AbstractAuthenticationProcessingFilter
        // for redirection after successful authentication (SEC-29)
        request.getSession().setAttribute(this.sessionAttrName, savedRequest);
        logger.debug("DefaultSavedRequest added to Session: " + savedRequest);
}

so createSessionAllowed || request.getSession(false) != null always true and session to be created in any case. You can change this with XML configuration - please see the last reply in https://stackoverflow.com/questions/14176853/how-to-stop-spring-security-from-creating-a-new-session or, if you use Java config, you can do following:

public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
        public HttpSessionRequestCache getHttpSessionRequestCache() {
            HttpSessionRequestCache httpSessionRequestCache = new HttpSessionRequestCache();
            httpSessionRequestCache.setCreateSessionAllowed(false);
            return httpSessionRequestCache;
        }

        @Override
        protected void configure(final HttpSecurity http) throws Exception {
            http.requestCache().requestCache(getHttpSessionRequestCache());
}

Comment From: eaglerainbow

@alex-exelweb Thanks a lot for your suggestion! You really saved me from a lot of trouble.

Like @theloom I am puzzled on this behavior. In my case, not having form-based authentication but OAuth2 in place, I even had specified

httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);

Yet, the HttpSessionRequestCache has a different opinion on it by implicitly setting createSessionAllowed == true. So I am wondering, why those two configuration options are not connected with each other (say: if session creation policy is disabled, why not also disable the Request Cache to ensure that no sessions are created in case of an authentication error/missing authentication). In my eyes, we can debate now whether this is just counter-intuitive or even a bug: I don't want to know how many spring applications are out there, which you could DoS-crash due to memory suffrage on sending a massive amount of garbage HTTP requests, because they followed the best practice of specifying httpSecurity.sessionManagement().anyRequest().denyAll() as fallback rule.

PS: Reproducible for me up to spring-boot 1.5.8

Comment From: atrifyllis

In a related scenario, I have oauth2 with form login and if I use the HttpSessionRequestCache workaround, after redirect from login page no auth token is passed to my client app. This has to do with SavedRequestAwareAuthenticationSuccessHandler which uses the session to retrieve redirect info. Is this normal behavior?

Comment From: natetyler

I am seeing this as well, I think it's reasonable to expect the cache to respect the configured SessionCreationPolicy.

Comment From: GauravWable

I have tried to set create session allowed = false, but didn't work. My WebSecurityConfig file is as follows:

` @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private AADAuthenticationFilter aadAuthFilter;

public HttpSessionRequestCache getHttpSessionRequestCache() {
    HttpSessionRequestCache httpSessionRequestCache = new HttpSessionRequestCache();
    httpSessionRequestCache.setCreateSessionAllowed(false);
    return httpSessionRequestCache;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    // Stateless session for APIs
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.requestCache().requestCache(getHttpSessionRequestCache());

    // Disable Cookies
    http.csrf().disable().authorizeRequests()
        //.antMatchers(HttpMethod.OPTIONS,"/api/**").permitAll()//allow CORS option calls
        .antMatchers("/api/v1/**").authenticated() // request matcher for authenticate user, Authenticated user can access all apis
        .and().httpBasic();

    // Add Active Directory filter
    http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);

}

}

`

What should be done to disable user session ?

Comment From: rwinch

There are many places where HttpSession can be created the session management is around authentication aspect only. I'd add @EnableWebSecurity(debug = true) which will let you know where the session is being created.

Comment From: netbeansuser2019

This happens because of Spring standard implementation of HttpSessionRequestCache: private boolean createSessionAllowed = true; And if (createSessionAllowed || request.getSession(false) != null) { // Store the HTTP request itself. Used by // AbstractAuthenticationProcessingFilter // for redirection after successful authentication (SEC-29) request.getSession().setAttribute(this.sessionAttrName, savedRequest); logger.debug("DefaultSavedRequest added to Session: " + savedRequest); }

so createSessionAllowed || request.getSession(false) != null always true and session to be created in any case. You can change this with XML configuration - please see the last reply in https://stackoverflow.com/questions/14176853/how-to-stop-spring-security-from-creating-a-new-session or, if you use Java config, you can do following: public class ApiSecurityConfig extends WebSecurityConfigurerAdapter { public HttpSessionRequestCache getHttpSessionRequestCache() { HttpSessionRequestCache httpSessionRequestCache = new HttpSessionRequestCache(); httpSessionRequestCache.setCreateSessionAllowed(false); return httpSessionRequestCache; }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.requestCache().requestCache(getHttpSessionRequestCache());

}

May you can use also: org.springframework.security.web.savedrequest.NullRequestCache

Comment From: rwinch

Closing. As mentioned there are plenty of places a session can be created and the setting is only for authentication. If you have a specific issue please provide a complete sample to reproduce the issue.