302 instead of 200 when using custom AuthenticationFailureHandler

When I don’t specify a custom AuthenticationFailureHandler in my WebSecurityConfigurerAdapter, the request is redirected to the default “/login?error” with status 200. When I add a custom implementation which only delegates handling authentication failure to the default implementation:

public class SomeCustomHandler implements AuthenticationFailureHandler {

  private final SimpleUrlAuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler("/login?error");

  @Override
  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    authenticationFailureHandler.onAuthenticationFailure(request, response, exception);
  }
}

WebSecurityConfigurerAdapter:

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
      .requestMatchers()
      .antMatchers("/login", "/oauth/authorize")
    .and()
      .authorizeRequests()
      .anyRequest().authenticated()
    .and()
      .formLogin()
      .loginPage("/login")
      .failureHandler(new SomeCustomHandler())
    .permitAll();

}

I receive 302 and redirection to no-error login page. Could anyone explain why? enter image description here

Answer

The behaviour you are seeing is /login?error redirecting to /login because it is secured.

When you do not have a custom failure handler Spring Security is aware of your login URL and your login failure URL.
By adding .permitAll() to your configuration Spring Security will allow all requests to both the login URL and the login failure URL, since it knows what they both are.

When you add a custom failure handler, Spring does not know what your login failure URL will be, or even whether you will have a failure URL, since you are handling that logic yourself.
Therefore .permitAll() is only applied to the login URL.
If you don’t want /login?error to be secured, you will have to set that configuration yourself. You can do something like:

http
    .authorizeRequests()
        .antMatchers("/login*").permitAll()
        .anyRequest().authenticated()
...

Leave a Reply

Your email address will not be published. Required fields are marked *