After upgrading from Boot 2.6.3 to 2.6.4 we found out that in cases where our service that's secured via Spring Security throws an exception resulting in a 401 or 403 response, the internal forward to Boot's /error page no longer works and an HTTP response is returned that's missing the JSON-marshalled error attributes. After some trial and error I found out that this only happens with the 5.6.2 version of Spring Security that's provided as a managed dependency by Boot 2.6.4, NOT with the previous 5.6.1 version.
I've attached a simple application with an integration test that demonstrates the issue: spring-boot-errorpage-security-issue.zip
When you edit the pom.xml to downgrade to Spring Security 5.6.1, the testcase passes as the error page is rendered as expected. As given however, a 403 response without any response body is returned. The same thing happens when you change the exception to result in a 401 rather than a 403: the response will have the expected status code, but no error is rendered. When you enable debug logging it becomes clear that the DispatcherServlet is never called to render the /error page; somehow Spring Security is preventing it from happening with 5.6.2.
Since I haven't investigated the root cause yet I'm not 100% sure if this is a Spring Boot issue or a Spring Security issue, so I'm reporting this here for now.
Comment From: jkuipers
I noticed that when you explicitly allow access by adding .mvcMatchers("/error").permitAll() the error page works as expected. Apparently the authorization check is triggered with 5.6.2 even though we're dealing an ERROR dispatch to the Boot-configured /error path.
Comment From: krishnaprasadpadala
Hi @jkuipers ,
Yes, I too noticed the same thing that authorization is getting triggered for error page as well.
I've tried to make a small change in the code snippet that you have shared and test case got success. .mvcMatchers("/", "/error") . I'm really not sure if this is the ideal solution but this helps in not downgrading to Spring security 5.6.1.
Hope this helps. Thankyou.
Comment From: wilkinsona
Thanks for the sample, @jkuipers. I believe that the change in behavior is due to the changes made for https://github.com/spring-projects/spring-security/issues/10680. They appear to have exposed a problem with the matchers in your security configuration.
I don't fully understand what's going on with the matchers in Spring Security, but your configuration is resulting in AnyRequestMatcher being used to determine what should be secured at one point and an MvcMatcher to be used when Boot calls the WebInvocationPrivilegeEvaluator. Curiously, it works when changing from authorizeHttpRequests to authorizeRequests. In both cases, Spring Boot is passing the same inputs into the WebInvocationPrivilegeEvaluator so I think this'll have to be addressed in Spring Security.
Please open a Spring Security issue and comment here with a link to it.
Comment From: jkuipers
Thanks for looking into this, Andy! (esp. during the weekend) I've opened up https://github.com/spring-projects/spring-security/issues/10937 to report this as a Spring Security issue now.
Comment From: jkuipers
Issue will be fixed in Spring Security 5.6.3.
Comment From: jkuipers
This issue is back when you use Spring Boot 3 with Spring Security 6. This seems to be caused by a change in Spring Security that now includes ERROR in the list of DispatcherTypes for which the security filter chain is triggered.
I was wondering if the Boot 3 / Security 6 combination is now working as it should be, and I'm expected to explicitly unsecure /error or exclude the ERROR type, or if this is a bug / shortcoming of Boot's autoconfiguration.
Comment From: philwebb
@jkuipers We're trying to align with Spring Security so we believe that things are working as expected. See #33934 for more discussion and specifically this comment: https://github.com/spring-projects/spring-boot/issues/33934#issuecomment-1441177170
Comment From: jkuipers
Thanks for confirming that this works as expected!
Comment From: jorgerod
I have the same error with Spring Boot 3 and Spring Security 6.
@jkuipers Did you solve the problem? @wilkinsona I think the issue should be reopened
Comment From: wilkinsona
Sorry, I don't think we're going to re-open this issue.
Boot's behavior is now aligned with Spring Security's which we think is the right thing to do. As Phil mentioned above, please see https://github.com/spring-projects/spring-boot/issues/33934 for more discussion and specifically this comment: https://github.com/spring-projects/spring-boot/issues/33934#issuecomment-1441177170.
As @jkuipers describes above, you can either explicitly unsecure /error or excludeERROR from the security filter's dispatcher types.