I've been trying to update one Spring Boot project today from 2.5.8 to 2.6.2. However the introduction of ErrorPageSecurityFilter causes me quite some headache. I've read a few other issues that say it's fixed now, but I cannot find a way to make my use case work:

We have a client that tries to authenticate with the Spring Boot server. Before the update, it would just sent 401 and a message containing the reason for the failure. When no message is returned (like now) the client assumes some sort of Internal Server Error. The way this is implemented is that we have an AuthenticationFailureHandler that handles AuthenticationException during the authentication process and then essentially calls response.sendError(HttpServletResponse.SC_UNAUTHORIZED, exception.message).

Now the suggestion with the new filter as far as I understood is to permit access to "/error" to explicitly allow this behavior. However that will never work as the WebInvocationPrivilegeEvaluator when isAllowed() is called, checks if (authentication == null) return false; and I don't have an authentication since it just failed to authenticate. Even if I try to set one, it gets removed.

I would be completely fine with just disabling the new filter entirely, but this seems to be extremely difficult? I've tried setting the property server.error.include-message=always, but as far as I can see that changes nothing. Creating my own FilterRegistrationBean<ErrorPageSecurityFilter> and setting setEnabled(false) doesn't work. I can't simply exclude the ErrorPageSecurityFilterConfiguration since it's not an AutoConfiguration and/or package private. I've tried wrapping the DefaultWebInvocationPrivilegeEvaluator to always allow /error, but that is getting nowhere because in the WebSecurityConfigurerAdapter the constructor argument FilterSecurityInterceptor has no public getter and it apparently gets passed by some complicated mechanism.

So obviously, if the default configuration had been like this from the start, we would have never designed the flow like this; but I feel like the current behavior should be easier to opt-out of.

Comment From: wilkinsona

Thanks for the report, @xcq1.

There have been some improvements in this area in Spring Security. The details are in https://github.com/spring-projects/spring-security/issues/10554, the changes for which have been backported to the yet-to-be-released 5.6.2 and 5.5.5. The gist is that things should now work better with multiple security filter chains and when a URL is covered by ignoring(), i.e. when there's no Authentication.

Could you please give your app a try with Spring Security 5.6.2-SNAPSHOT available from https://repo.spring.io/snapshot and let us know how you get on? If it doesn't help, could you please share a small sample application that reproduces the problem that you're facing? You can share it with us by zipping it up and attaching it to this issue or pushing it to a separate repository in GitHub. In the meantime, you may also be interested in this workaround which should work equally well in main code. It'll remove the filter entirely.

Comment From: xcq1

Thanks @wilkinsona, those are excellent news. I can confirm that building with Spring Security 5.6.2-SNAPSHOT fixes my problem. The filter is called, but isAllowed returns true as expected. The workaround that you mentioned works as well, so I can bump to Boot 2.6.2 for now, and I guess this will do until the proper patch drops in the coming months.

Comment From: wilkinsona

Thanks very much for trying the security snapshot, @xcq1. It's great to hear that it fixes your problem. I'll close this one as a duplicate of the security issues. We'll pick up the Security maintenance releases in due course.