Reputation: 732
I have a custom MyAuthenticationProvider
. It throws a custom MyException
, which extends BadCredentialsException. It seems to work for success and failure authentication, but for failures it doesn't seem to trigger publishing an authentication failure event.
"DefaultAuthenticationEventPublisher : No event was found for the exception MyException"
I copy-and-pasted this code from Authentication Events - Default Event for triggering publication of unmapped exceptions, but it didn't work for me.
@Bean
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
DefaultAuthenticationEventPublisher authenticationEventPublisher = new DefaultAuthenticationEventPublisher(applicationEventPublisher);
authenticationEventPublisher.setDefaultAuthenticationFailureEvent(AbstractAuthenticationFailureEvent.class);
return authenticationEventPublisher;
}
The "No event was found for the exception" log comes from DefaultAuthenticationEventPublisher.publishAuthenticationFailure
, so I set a breakpoint. I walked through the method, and it seems like the constructor.newInstance(authentication, exception)
silently fails.
@Override
public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
Constructor<? extends AbstractAuthenticationEvent> constructor = getEventConstructor(exception);
AbstractAuthenticationEvent event = null;
if (constructor != null) {
try {
event = constructor.newInstance(authentication, exception);
}
catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) {
}
}
if (event != null) {
if (this.applicationEventPublisher != null) {
this.applicationEventPublisher.publishEvent(event);
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("No event was found for the exception " + exception.getClass().getName());
}
}
}
The constructor call failed because the docs told me to use is AbstractAuthenticationFailureEvent. Furthermore, the catch ignores the exception.
To test my theory, I changed the workaround from the doc to use a concrete class instead of AbstractAuthenticationFailureEvent. That worked, because my unmapped exception triggered publishing a failure event now.
@Bean
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
DefaultAuthenticationEventPublisher authenticationEventPublisher = new DefaultAuthenticationEventPublisher(applicationEventPublisher);
authenticationEventPublisher.setDefaultAuthenticationFailureEvent(UnmappedAuthenticationFailureEvent .class);
return authenticationEventPublisher;
}
public static class UnmappedAuthenticationFailureEvent extends AbstractAuthenticationFailureEvent {
public UnmappedAuthenticationFailureEvent(Authentication authentication, AuthenticationException exception) {
super(authentication, exception);
}
}
Questions:
I think the answer to both is yes. If you agree, could you:
publishAuthenticationFailure
catch.Thank you.
P.S. I think a diagnostic log would be especially helpful. It was frustrating and time consuming trying to figure out why the official solution from the docs did not work. P.P.S I would also like to point out that searching for workarounds in Stack Exchange, search engines, and AI chatbots did not help. A diagnostic log would be more effective.
Upvotes: 0
Views: 42