Search code examples
javaspringspring-securityjwtjjwt

Spring security add ApplicationEventListener to ExpiredJwtException


I had implemented AuthenticationFailureListener for fail login by using ApplicationListener<AuthenticationFailureBadCredentialsEvent> and all my Bad Credentials event are handeled in the same class, very convenient, I have tried to add a Listener to ExpiredJwtException or SignatureException but I could not figure which event is triggered, I have tried -

@Component
public class ApplicationEventListener implements ApplicationListener<ApplicationEvent>{

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event.toString()); //not printed when ExpiredJwtException thrown
    }
}

to catch all ApplicationEvent but when one of this exception happens the method onApplicationEvent does not fired. I can catch this Exceptions but I want to handle them globally like BadCredentialsException is handled by AuthenticationFailureBadCredentialsEvent. Tried AuthenticationFailureExpiredEvent -

@Component
public class ApplicationEventListener implements ApplicationListener<AuthenticationFailureExpiredEvent>{

    @Override
    public void onApplicationEvent(AuthenticationFailureExpiredEvent event) {
        System.out.println("Expired!!"); //same result
    }
}

but still not working.


Solution

  • I'm not sure about this, I would have to check the source, but: it could be that an application event is not emitted for ExpiredJwtException or SignatureException.

    Possible solutions are:

    1. Publish the event yourself: as you mentioned you are able to catch these exceptions, so a simple solution would be to catch them and then emit the desired event. You just need to autowire the ApplicationEventPublisher and then call publishEvent(event).

    2. Use a Filter to catch and handle the exceptions in a single place.

    Example of solution 2:

    public class AuthFailureFilter extends GenericFilterBean {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            try {
                chain.doFilter(request, response);
            } catch (ExpiredJwtException | SignatureException exception) {
                handle(exception);
            }
        }
    }