Itsik Mauyhas
Itsik Mauyhas

Reputation: 3984

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.

Upvotes: 1

Views: 859

Answers (2)

ESala
ESala

Reputation: 7058

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);
        }
    }
}

Upvotes: 0

sanchedale
sanchedale

Reputation: 166

I think the easiest way to publish an ApplicationEvent when catching exceptions is by using the ApplicationEventPublisher. There is no need to implement ApplicationEvent using this method as it wraps any object into a PayloadApplicationEvent that you can use in your ApplicationEventListener and act on it. This works from Spring 4.2 and here is the official link: https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2

Upvotes: 1

Related Questions