title: Spring Boot exception handler with Spring Security
body: <p>I have a spring boot 1.3.0.BUILD-SNAPSHOT app that has Spring Security.  I have a @ControllerAdvice class for using in handling exceptions from my endpoints, and that works well.  However, I am unable to track exceptions from Spring Security such as AuthenticationException.  I use this to catch those exceptions and log a specific message:</p>
  
  <pre><code>@Component
  public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
  
      @Override
      public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
          request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception.getLocalizedMessage());
          throw new SessionAuthenticationException(exception.getLocalizedMessage());
      }
  }
  </code></pre>
  
  <p>The exception is never caught even though I have this:</p>
  
  <pre><code>@ControllerAdvice
  public class BaseController {
      @ExceptionHandler({SessionAuthenticationException.class})
      @ResponseBody
      public ResponseEntity getSessionAuthenticationExceptionResponse(Exception exception) {
  
          LOGGER.error("exception.getMessage()", exception);
          return  ResponseEntity.status( HttpStatus.UNAUTHORIZED )
                          .contentType( MediaType.APPLICATION_JSON ).body( exception.getLocalizedMessage() );
  
      }
  ..}
  </code></pre>
  
  <p>And here is my configuration:</p>
  
  <pre><code>@ComponentScan
  @EnableAutoConfiguration
  @EnableGlobalMethodSecurity(securedEnabled = true)
  @SpringBootApplication
  public class EDentalManager extends WebMvcConfigurerAdapter  {
  ...
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
            .addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
            ...
            .and()
            .formLogin()
            .loginPage("/loginPage")
            .permitAll()
            .loginProcessingUrl("/login")
            .defaultSuccessUrl("/?tab=success")
            .failureHandler(authenticationFailureHandler)
            .and()
            .logout().addLogoutHandler(logoutHandler).logoutRequestMatcher( new AntPathRequestMatcher("/logout"))
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true).permitAll().and().csrf()
            .and()  
            .sessionManagement()
            .withObjectPostProcessor(new AdditionalStrategyPostProcessor(new CleanRegistry(sessionRegistry)))
             .sessionFixation().changeSessionId()
             .maximumSessions(1)
             .maxSessionsPreventsLogin(true)
             .expiredUrl("/login?expired" )
             .sessionRegistry(sessionRegistry )
             .and()
             .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
             .invalidSessionUrl("/")
             .and().authorizeRequests().anyRequest().authenticated();
      }
  }
  </code></pre>
  
  <p>What is the best way to trap Spring Security exceptions so I can message the user in case of too-many sessions, authentication exceptions, etc?</p>
  
  <p><strong>Update</strong> based upon latest findings:</p>
  
  <pre><code>public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  
      @Autowired
      private MessageSource messages;
  
      @Autowired
      private LocaleResolver localeResolver;
  
      @Override
      public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response,
                                          final AuthenticationException exception) throws IOException, ServletException {
  
          final Locale locale = localeResolver.resolveLocale(request);
          String errorMessage = buildErrorMessage(response, exception, locale);
          response.setHeader("Authentication Error", errorMessage);
          response.setStatus(HttpStatus.UNAUTHORIZED.value());
          response.sendError(HttpStatus.UNAUTHORIZED.value(), errorMessage);
      }
  
      private void buildErrorMessage(final HttpServletResponse response, Exception exception, Locale locale) {
  
                 String errorMessage = messages.getMessage("message.badCredentials", null, locale);
      response.setStatus(HttpStatus.UNAUTHORIZED.value());
  
      if (exception instanceof BadCredentialsException) {
          errorMessage = messages.getMessage("auth.message.invalid.credentials", null, locale);
      } else if (exception.getMessage().equalsIgnoreCase("User is disabled")) {
          errorMessage = messages.getMessage("auth.message.disabled", null, locale);
      } else if (exception.getMessage().equalsIgnoreCase("User account has expired")) {
          errorMessage = messages.getMessage("auth.message.expired", null, locale);
      } else if (exception.getMessage().equalsIgnoreCase("blocked")) {
          errorMessage = messages.getMessage("auth.message.blocked", null, locale);
      } else {
          errorMessage = exception.getMessage();
      }
  }
  </code></pre>
  
  <p>I am now redirected to error.html after my /login POST and I see a 401 ResponseStatus, and I have the header information I put on the response.  </p>
  
  <p>This seems like it should be handled without a redirect and with a ResponseEntity, but that doesn't appear the way Spring Boot &amp; Security handle it.  Can anyone suggest a cleaner approach to this messaging authentication events without using Thymeleaf (we are pure http ->json ->Tomcat)?  </p>