Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Websocket XHR fallbacks get IllegalStateException: Cannot create a session after the response has been committed upgrading to Boot 3.2.7 #14864

Open
stnor opened this issue Apr 8, 2024 · 7 comments
Assignees
Labels
in: saml2 An issue in SAML2 modules status: feedback-provided Feedback has been provided

Comments

@stnor
Copy link

stnor commented Apr 8, 2024

Describe the bug
I recently upgraded from Boot 2.7 to 3.2.7.
Since then I am getting a lot of java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:99)`

2024-04-08T10:39:14.519+02:00 E o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] threw exception
java.lang.IllegalStateException: Cannot create a session after the response has been committed`

It seems to be related to Websocket requests that fallback to XHR:
[08/Apr/2024:10:39:14 +0200] "POST /ws/684/0jl1hqqe/xhr_streaming?t=1712565509691 HTTP/1.1" 500 83 "***" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" 50009522

I am using requireExplicitSave = false for the context and SessionCreationPolicy.ALWAYS

SecurityConfig:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http,
                                           RelyingPartyRegistrationResolver rpResolver,
                                           SkolfedSamlResponseAuthenticationConverter authConverter) throws Exception {
        // Begin SAML
        var authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(rpResolver);
        authenticationRequestResolver.setRequestMatcher(new AntPathRequestMatcher("/saml/login"));
        var authenticationProvider = new OpenSaml4AuthenticationProvider();
        authenticationProvider.setResponseAuthenticationConverter(authConverter);
        http.saml2Login(samlLogin ->
                samlLogin
                        .loginPage(DISCOVERY_URL)
                        .successHandler(samlSuccessRedirectHandler())
                        .failureHandler(new SamlAuthenticationFailureHandler())
                        .authenticationManager(new ProviderManager(authenticationProvider))
                        .authenticationRequestResolver(authenticationRequestResolver)
                        .authenticationConverter(new Saml2AuthenticationTokenConverter(rpResolver))
                        .loginProcessingUrl("/saml/SSO"));
        // End SAML

        http.csrf(AbstractHttpConfigurer::disable);
        http.securityContext((securityContext) -> securityContext
                .securityContextRepository(new HttpSessionSecurityContextRepository())
                .requireExplicitSave(false)
        );
        http.addFilterAt(concurrencyFilter(), ConcurrentSessionFilter.class)
                .addFilterAt(nompRememberMeAuthenticationFilter(), RememberMeAuthenticationFilter.class)
                .addFilterBefore(new NompJwtAuthenticationFilter(nompJwtIssuer()), BasicAuthenticationFilter.class)
                .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.ALWAYS).sessionAuthenticationStrategy(sas()));
        return http.build();
    }

```

@stnor stnor added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Apr 8, 2024
@jzheaux
Copy link
Contributor

jzheaux commented Apr 16, 2024

Thanks, @stnor, and sorry you are having trouble.

I imagine that the SAML, JWT, and other pieces of configuration are unrelated. Would you be able to post a minimal GitHub sample that reproduces the issue?

@jzheaux jzheaux added status: waiting-for-feedback We need additional information before we can continue in: saml2 An issue in SAML2 modules and removed status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Apr 16, 2024
@jzheaux jzheaux self-assigned this Apr 16, 2024
@spring-projects-issues
Copy link

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Apr 23, 2024
@stnor
Copy link
Author

stnor commented Apr 24, 2024

I was able to recreate this locally a few times (it seems pretty rare) with:

curl -X POST http:\/\/127.0.0.1:8080\/ws\/684\/0jl1hqqe\/xhr_streaming\?t=1712565509693

I don't fully understand what it takes to get the error to occur, but it's related to SecurityContextPersistenceFilter and eager session creation. The exception seems to pop up much later than I do anything with curl...

Any ideas on how to proceed would be appreciated.

java.lang.IllegalStateException: Cannot create a session after the response has been committed
	at org.apache.catalina.connector.Request.doGetSession(Request.java:2907)
	at org.apache.catalina.connector.Request.getSession(Request.java:2381)
	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:639)
	at jakarta.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:221)
	at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:553)
	at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:500)
	at jakarta.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:229)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:99)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue labels Apr 24, 2024
@stnor
Copy link
Author

stnor commented Apr 24, 2024

When I'm setting a breakpoint at SecurityContextPersistenceFilter:99 I get one invocation per request I make with curl.

But then I sometimes get another invocation a bit later... What would cause a this code to get initiated, not related to an http-request initiated by me?

The ApplicationHttpRequest.requestDispatcherPath is set to "/error" already.

Screenshot 2024-04-24 at 13 28 10

@stnor
Copy link
Author

stnor commented Apr 24, 2024

The filterChain (when I get the error), currentPosition is 5.

Oddly, the ForceEagerSessionCreationFilter is twice in the list...

Screenshot 2024-04-24 at 13 50 29

@stnor
Copy link
Author

stnor commented Apr 24, 2024

There seems to be a nested java.io.IOException: Broken pipe that causes this, which would explain the random/delayed invocation.

See errorException here:
Screenshot 2024-04-24 at 13 59 47

@stnor
Copy link
Author

stnor commented Apr 29, 2024

Any ideas how the "Broken Pipe" related exceptions end up here @jzheaux?

These "errors" are ineviatable for websockets given that people close their laptops etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: saml2 An issue in SAML2 modules status: feedback-provided Feedback has been provided
Projects
None yet
Development

No branches or pull requests

3 participants