Skip to content

Commit 51b9b2f

Browse files
zeeshanadnanjzheaux
authored andcommitted
DefaultAuthenticationEventPublisher Default Event
Fixes gh-7825
1 parent a90e579 commit 51b9b2f

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java

+28
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
6464

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

6869
public DefaultAuthenticationEventPublisher() {
6970
this(null);
@@ -117,6 +118,13 @@ public void publishAuthenticationFailure(AuthenticationException exception,
117118
catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) {
118119
}
119120
}
121+
else if (defaultAuthenticationFailureEventConstructor != null) {
122+
try {
123+
event = defaultAuthenticationFailureEventConstructor.newInstance(authentication, exception);
124+
}
125+
catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) {
126+
}
127+
}
120128

121129
if (event != null) {
122130
if (applicationEventPublisher != null) {
@@ -163,6 +171,26 @@ public void setAdditionalExceptionMappings(Properties additionalExceptionMapping
163171
}
164172
}
165173

174+
/**
175+
* Sets a default authentication failure event as a fallback event for any unmapped
176+
* exceptions not mapped in the exception mappings.
177+
*
178+
* @param defaultAuthenticationFailureEventClass is the authentication failure event class
179+
* to be fired for unmapped exceptions.
180+
*/
181+
public void setDefaultAuthenticationFailureEvent(
182+
Class<? extends AbstractAuthenticationFailureEvent> defaultAuthenticationFailureEventClass) {
183+
Assert.notNull(defaultAuthenticationFailureEventClass,
184+
"The defaultAuthenticationFailureEventClass must not be null");
185+
try {
186+
this.defaultAuthenticationFailureEventConstructor = defaultAuthenticationFailureEventClass
187+
.getConstructor(Authentication.class, AuthenticationException.class);
188+
} catch (NoSuchMethodException e) {
189+
throw new RuntimeException("Default Authentication Failure event class "
190+
+ defaultAuthenticationFailureEventClass.getName() + " has no suitable constructor");
191+
}
192+
}
193+
166194
private void addMapping(String exceptionClass,
167195
Class<? extends AbstractAuthenticationFailureEvent> eventClass) {
168196
try {

core/src/test/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisherTests.java

+32
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent;
2828
import org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent;
2929
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
30+
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
3031
import org.springframework.security.core.Authentication;
3132
import org.springframework.security.core.AuthenticationException;
3233
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -137,6 +138,37 @@ public void unknownFailureExceptionIsIgnored() {
137138
verifyZeroInteractions(appPublisher);
138139
}
139140

141+
@Test(expected = IllegalArgumentException.class)
142+
public void defaultAuthenticationFailureEventClassSetNullThen() {
143+
publisher = new DefaultAuthenticationEventPublisher();
144+
publisher.setDefaultAuthenticationFailureEvent(null);
145+
}
146+
147+
@Test
148+
public void defaultAuthenticationFailureEventIsPublished() {
149+
publisher = new DefaultAuthenticationEventPublisher();
150+
publisher.setDefaultAuthenticationFailureEvent(AuthenticationFailureBadCredentialsEvent.class);
151+
ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class);
152+
153+
publisher.setApplicationEventPublisher(appPublisher);
154+
publisher.publishAuthenticationFailure(new AuthenticationException("") {
155+
}, mock(Authentication.class));
156+
verify(appPublisher).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class));
157+
}
158+
159+
@Test(expected = RuntimeException.class)
160+
public void defaultAuthenticationFailureEventMissingAppropriateConstructorThen() {
161+
publisher = new DefaultAuthenticationEventPublisher();
162+
publisher.setDefaultAuthenticationFailureEvent(AuthenticationFailureEventWithoutAppropriateConstructor.class);
163+
}
164+
165+
private static final class AuthenticationFailureEventWithoutAppropriateConstructor extends
166+
AbstractAuthenticationFailureEvent {
167+
AuthenticationFailureEventWithoutAppropriateConstructor(Authentication auth) {
168+
super(auth, new AuthenticationException("") {});
169+
}
170+
}
171+
140172
private static final class MockAuthenticationException extends
141173
AuthenticationException {
142174
MockAuthenticationException(String msg) {

0 commit comments

Comments
 (0)