It’s just plain hard to get true, real-time visibility into a running auth flow.

Parts of the process can be completely hidden from us; if the complete authorization process requires a redirect from a remote OAuth production server, then every debugging effort must go through the production server.

It’s practically unfeasible to debug this locally. There’s no way to reproduce the exact state and no way to inspect what is actually happening under the hood. Not ideal.

Knowing these types of challenges, we built Lightrun - a real-time production debugging tool - to allow you to understand complicated flows with code-level information. Add logs, take snapshots (virtual breakpoints), and instrument metrics without a remote debugger, without stopping the running service, and, most importantly - in real-time and without side effects.

Learn more with this 5-minute tutorial focused on debugging these kinds of scenarios using Lightrun:

>> Debugging Authentication and Authorization Using Lightrun

1. Overview

In this article, we'll have a look at how to handle Spring Security exceptions produced by our Spring Security Resource Server. To do so, we'll also use a practical example where all the necessary configurations will be explained. First of all, let's make a short introduction to Spring Security.

2. Spring Security

Spring Security is a library that's part of the Spring project. It tries to group all the functionalities of user access control on Spring projects. Access control allows limiting the options that can be executed by a given set of users or roles on the application. In this direction, Spring Security controls invocations to business logic or limits the access of HTTP requests to certain URLs. With this in mind, we must configure the application by telling Spring Security how the security layer should behave.

In our case, we'll focus on the configuration of exception handlers. Spring Security offers three different interfaces to accomplish this purpose and to control the events produced:

  • Authentication Success Handler
  • Authentication Failure Handler
  • Access Denied Handler

Firstly, let's take a closer look at the configuration.

3. Security Configuration

First of all, we've our configuration class that has to extend the WebSecurityConfigurerAdapter class. This will be in charge of managing all the security configurations of the application. So, it's here where we have to introduce our handlers.

On the one hand, we'll define the required configuration:

protected void configure(HttpSecurity http) throws Exception {

It's interesting to note that redirection URLs, such as “/login”, “/customError”, and “/access-denied” don't have to have any type of restriction to access them. So, we annotate them as permitAll().

On the other hand, we've to define the Beans that define the types of exceptions that we can handle:

public AuthenticationFailureHandler authenticationFailureHandler() {
    return new CustomAuthenticationFailureHandler();

public AuthenticationSuccessHandler authenticationSuccessHandler() {
   return new CustomAuthenticationSuccessHandler();

public AccessDeniedHandler accessDeniedHandler() {
   return new CustomAccessDeniedHandler();

Since the AuthenticationSuccessHandler handles the happy path, we'll define the two remaining beans for the exception cases. These two handlers are the ones we now have to adapt and implement to our needs. So, let's proceed with the implementation of each of them.

4. Authentication Failure Handler

On the one hand, we've got the AuthenticationFailureHandler interface. That's in charge of managing the exceptions produced when the user fails to log in. This interface provides us with the onAuthenticationFailure() method to customize the handler logic. It will be invoked by Spring Security upon a failed login attempt. With this in mind, let's define our exception handler to redirect us to the error page when a failed login occurs:

public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) 
      throws IOException {

5. Access Denied Handler

On the other hand, when an unauthorized user tries to access the secure or protected page, Spring Security will throw an access denied exception. There's a default 403 access denied page available with Spring Security which we can customize. This is managed by the AccessDeniedHandler interface. In addition, it provides the handle() method for custom the logic before redirecting the user to the 403 page:

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException {

6. Conclusion

In this quick article, we've learned how to handle Spring Security exceptions and how to control them by creating and customizing our classes. In addition, we've created a fully functional example that helps us with understanding the concepts explained.

The complete source code of the article is available over on GitHub.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

Security footer banner
Inline Feedbacks
View all comments