Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-10911

Authentication servlet filter tries to create a new session after response was committed

    XMLWordPrintable

    Details

    • Type: Bug Report
    • Status: Closed
    • Priority: L3 - Default
    • Resolution: Fixed
    • Affects Version/s: 7.12.0, spring-boot 3.4.0, spring-boot 3.3.5, spring-boot 3.2.7, spring-boot 3.1.7
    • Fix Version/s: 7.13.0, 7.13.0-alpha2, 7.12.3
    • Component/s: spring-boot, webapp
    • Labels:
      None

      Description

      Steps to reproduce
      Perform a modifying request with absent CSRF token

      Expected behavior
      I can see the following error message:

      CSRFPreventionFilter: Token provided via HTTP Header is absent/empty.
      

      Observed behavior
      I can see the following error message:

      java.lang.IllegalStateException: Cannot create a session after the response has been committed
      	at org.apache.catalina.connector.Request.doGetSession(Request.java:2993)
      	at org.apache.catalina.connector.Request.getSession(Request.java:2432)
      	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:908)
      	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:920)
      	at org.camunda.bpm.webapp.impl.security.auth.AuthenticationFilter.doFilter(AuthenticationFilter.java:68)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
      	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
      	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
      	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
      	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
      	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
      	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
      	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
      	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
      	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
      	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
      	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
      	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
      	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
      	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
      	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      	at java.base/java.lang.Thread.run(Thread.java:844)
      

      Root Cause

      • The AuthenticationFilter invokes FilterChain#doFilter which leads to advancing in the filter chain
        • there exists a finally block in which with HttpServletRequest#getSession the session is retrieved or created if absent
      • The CSRF prevention filter is registered after the AuthenticationFilter
        • If an error occurs the response is committed to send the error message to the client
        • This breaks the filter chain
      • Because the filter chain has ended, the finally block in AuthenticationFilter is executed and HttpServletRequest#getSession is called
      • This results in the error shown above because:
        1. The response has already been committed and therefore the session has ended
        2. The method invocation leads to the creation of a new session

      Solution

      • The exception could be avoided by passing false to HttpServletRequest#getSession(boolean create)
      • In this case null is returned and could be handled appropriately

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              yana.vasileva Yana Vasileva
              Reporter:
              tassilo.weidner Tassilo Weidner
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: