Spring Security
  1. Spring Security
  2. SEC-2054

BasicAuthenticationFilter should not invoke on ERROR dispatch

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Trivial Trivial
    • Resolution: Complete
    • Affects Version/s: 3.1.2
    • Fix Version/s: 4.0.0.RC1
    • Component/s: Core
    • Labels:

      Description

      I have configured the following security element:

      <security:http use-expressions="true" realm="My Application">
       
      		<security:intercept-url
      			pattern="/app/demo"
      			access="hasRole('Info')" />
       
      		<security:intercept-url
      			pattern="/app/**"
      			access="isAuthenticated()" />
       
      		<security:intercept-url
      			pattern="/admin/**"
      			access="hasRole('Admin')" />
       
      		<security:logout invalidate-session="true" delete-cookies="JSESSIONID"
      			logout-url="/logout" logout-success-url="/logout-success" />
       
      		<security:http-basic />
      </security:http>
      

      I have set up custom error pages in my web.xml:

      !-- error pages -->
      	<error-page>
      		<error-code>401</error-code>
      		<location>/errors/401</location>
      	</error-page>
       
      	<error-page>
      		<error-code>403</error-code>
      		<location>/errors/403</location>
      	</error-page>
       
      	<error-page>
      		<error-code>404</error-code>
      		<location>/errors/404</location>
      	</error-page>
      	
      	<error-page>
      		<error-code>500</error-code>
      		<location>/errors/500</location>
      	</error-page>
      

      If for example an authentication fails the 401 page should be displayed.

      Now, if a client sends an invalid Basic value the filter chain finds that and calls the 401 page through Tomcat. Unfortunately, the filter chain proxy does not know that this is one request with an error forward only.

      It fires the entire auth chain again:

      14:29:38.552 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/app'; against '/ext-resources/**'
      14:29:38.552 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/app'; against '/resources/**'
      14:29:38.552 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/app'; against '/rest/**'
      14:29:38.552 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /app at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
      14:29:38.552 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
      14:29:38.552 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
      14:29:38.552 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /app at position 2 of 9 in additional filter chain; firing Filter: 'LogoutFilter'
      14:29:38.553 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /app at position 3 of 9 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
      14:29:38.553 [http-8080-1] DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.BadCredentialsException: Invalid basic authentication token
      14:29:38.553 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
      14:29:38.553 [http-8080-1] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
      14:29:38.554 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/errors/401'; against '/ext-resources/**'
      14:29:38.554 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/errors/401'; against '/resources/**'
      14:29:38.554 [http-8080-1] DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/errors/401'; against '/rest/**'
      14:29:38.554 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /errors/401 at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
      14:29:38.554 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
      14:29:38.555 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
      14:29:38.555 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /errors/401 at position 2 of 9 in additional filter chain; firing Filter: 'LogoutFilter'
      14:29:38.555 [http-8080-1] DEBUG o.s.security.web.FilterChainProxy - /errors/401 at position 3 of 9 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
      14:29:38.555 [http-8080-1] DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.BadCredentialsException: Invalid basic authentication token
      14:29:38.555 [http-8080-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
      14:29:38.555 [http-8080-1] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
      

      Now the FilterSecurityInterceptor maintains an observeOncePerRequest property which tells him to observe checks only once. The FilterChainProxy does not have such a property which treats a subrequest a whole new request. The response gets reset twice and no output it written to the client.

      I could set the error pages to security="none" but I want to maintain the security context on all pages whether they are protected or not.

        Issue Links

          Activity

          Hide
          Rob Winch added a comment -

          Pushing to 4.0 partially due to time lines and partially due to passivity concerns

          Show
          Rob Winch added a comment - Pushing to 4.0 partially due to time lines and partially due to passivity concerns
          Hide
          Rob Winch added a comment -

          This is now resolved in master. I decided to focus on this specific problem at hand since we did not have concrete use cases for other Filter's and dispatches.

          Show
          Rob Winch added a comment - This is now resolved in master. I decided to focus on this specific problem at hand since we did not have concrete use cases for other Filter's and dispatches.
          Hide
          Michael Osipov added a comment -

          Thanks for the fix. Does it really suffice to extend from OncePerRequestFilter and it is guaranteed to be executed only once? Is it still valid to have this configuration though you responded this earlier?

          Show
          Michael Osipov added a comment - Thanks for the fix. Does it really suffice to extend from OncePerRequestFilter and it is guaranteed to be executed only once? Is it still valid to have this configuration though you responded this earlier?
          Hide
          Rob Winch added a comment -

          Since SPR-9895 has been resolved, yes it is suffice to extend OncePerRequestFilter. Please go ahead and give the latest snapshot a try. You will need to ensure to update your dependencies to use Spring 4.1.2.RELEASE and Spring Security 4.0.0.CI-SNAPSHOT. You can resolve SNAPSHOTs with maven using the following maven repository:

           
            <repositories>
              <repository>
                <id>snapshot</id>
                <url>http://repo.spring.io/libs-snapshot</url>
              </repository>
            </repositories>
          

          NOTE: You may notice that the commit contains a test to ensure this works. I also have ran this through a simple integration test to ensure the unit test is properly setup.

          Show
          Rob Winch added a comment - Since SPR-9895 has been resolved, yes it is suffice to extend OncePerRequestFilter. Please go ahead and give the latest snapshot a try. You will need to ensure to update your dependencies to use Spring 4.1.2.RELEASE and Spring Security 4.0.0.CI-SNAPSHOT. You can resolve SNAPSHOTs with maven using the following maven repository:   <repositories> <repository> <id>snapshot</id> <url>http://repo.spring.io/libs-snapshot</url> </repository> </repositories> NOTE: You may notice that the commit contains a test to ensure this works. I also have ran this through a simple integration test to ensure the unit test is properly setup.
          Hide
          Michael Osipov added a comment - - edited

          Thanks a lot Rob, I will add this repo to our local Nexus instance and will give it a try next week. I will update the issue with the outcome of the test soon.

          Show
          Michael Osipov added a comment - - edited Thanks a lot Rob, I will add this repo to our local Nexus instance and will give it a try next week. I will update the issue with the outcome of the test soon.

            People

            • Assignee:
              Rob Winch
              Reporter:
              Michael Osipov
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: