Skip to content

Commit

Permalink
Option for default event in DefaultAuthenticationEventPublisher
Browse files Browse the repository at this point in the history
  • Loading branch information
zeeshanadnan committed Feb 6, 2020
1 parent ee6df17 commit 7ccc489
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP

private ApplicationEventPublisher applicationEventPublisher;
private final HashMap<String, Constructor<? extends AbstractAuthenticationEvent>> exceptionMappings = new HashMap<>();
private Constructor<? extends AbstractAuthenticationFailureEvent> defaultAuthenticationFailureEventConstructor;

public DefaultAuthenticationEventPublisher() {
this(null);
Expand Down Expand Up @@ -114,6 +115,13 @@ public void publishAuthenticationFailure(AuthenticationException exception,
catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) {
}
}
else if (defaultAuthenticationFailureEventConstructor != null) {
try {
event = defaultAuthenticationFailureEventConstructor.newInstance(authentication, exception);
}
catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) {
}
}

if (event != null) {
if (applicationEventPublisher != null) {
Expand Down Expand Up @@ -160,6 +168,26 @@ public void setAdditionalExceptionMappings(Properties additionalExceptionMapping
}
}

/**
* Sets a default authentication failure event as a fallback event for any unmapped
* exceptions not mapped in the exception mappings.
*
* @param defaultAuthenticationFailureEventClass is the authentication failure event class
* to be fired for unmapped exceptions.
*/
public void setDefaultAuthenticationFailureEvent(
Class<? extends AbstractAuthenticationFailureEvent> defaultAuthenticationFailureEventClass) {
Assert.notNull(defaultAuthenticationFailureEventClass,
"The defaultAuthenticationFailureEventClass must not be null");
try {
this.defaultAuthenticationFailureEventConstructor = defaultAuthenticationFailureEventClass
.getConstructor(Authentication.class, AuthenticationException.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Default Authentication Failure event class "
+ defaultAuthenticationFailureEventClass.getName() + " has no suitable constructor");
}
}

private void addMapping(String exceptionClass,
Class<? extends AbstractAuthenticationFailureEvent> eventClass) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent;
import org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand Down Expand Up @@ -137,6 +138,37 @@ public void unknownFailureExceptionIsIgnored() {
verifyZeroInteractions(appPublisher);
}

@Test(expected = IllegalArgumentException.class)
public void defaultAuthenticationFailureEventClassSetNullThen() {
publisher = new DefaultAuthenticationEventPublisher();
publisher.setDefaultAuthenticationFailureEvent(null);
}

@Test
public void defaultAuthenticationFailureEventIsPublished() {
publisher = new DefaultAuthenticationEventPublisher();
publisher.setDefaultAuthenticationFailureEvent(AuthenticationFailureBadCredentialsEvent.class);
ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class);

publisher.setApplicationEventPublisher(appPublisher);
publisher.publishAuthenticationFailure(new AuthenticationException("") {
}, mock(Authentication.class));
verify(appPublisher).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class));
}

@Test(expected = RuntimeException.class)
public void defaultAuthenticationFailureEventMissingAppropriateConstructorThen() {
publisher = new DefaultAuthenticationEventPublisher();
publisher.setDefaultAuthenticationFailureEvent(AuthenticationFailureEventWithoutAppropriateConstructor.class);
}

private static final class AuthenticationFailureEventWithoutAppropriateConstructor extends
AbstractAuthenticationFailureEvent {
AuthenticationFailureEventWithoutAppropriateConstructor(Authentication auth) {
super(auth, new AuthenticationException("") {});
}
}

private static final class MockAuthenticationException extends
AuthenticationException {
MockAuthenticationException(String msg) {
Expand Down

0 comments on commit 7ccc489

Please sign in to comment.