Skip to content

Commit

Permalink
AuthenticationFailureEvent should publish once
Browse files Browse the repository at this point in the history
  • Loading branch information
jgrandja committed Dec 21, 2018
1 parent b838f7c commit be23ab8
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
boolean debug = logger.isDebugEnabled();
Expand Down Expand Up @@ -205,7 +206,7 @@ public Authentication authenticate(Authentication authentication)
// handled the request
}
catch (AuthenticationException e) {
lastException = e;
lastException = parentException = e;
}
}

Expand Down Expand Up @@ -234,7 +235,11 @@ public Authentication authenticate(Authentication authentication)
"No AuthenticationProvider found for {0}"));
}

prepareException(lastException, authentication);
// If the parent AuthenticationManager was attempted and failed than it will publish an AbstractAuthenticationFailureEvent
// This check prevents a duplicate AbstractAuthenticationFailureEvent if the parent AuthenticationManager already published it
if (parentException == null) {
prepareException(lastException, authentication);
}

throw lastException;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

package org.springframework.security.authentication;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.springframework.context.MessageSource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;
import org.springframework.context.MessageSource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.*;

/**
* Tests {@link ProviderManager}.
Expand Down Expand Up @@ -257,7 +259,6 @@ public void authenticationExceptionFromParentOverridesPreviousOnes() throws Exce
catch (BadCredentialsException e) {
assertThat(e).isSameAs(expected);
}
verify(publisher).publishAuthenticationFailure(expected, authReq);
}

@Test
Expand Down Expand Up @@ -298,6 +299,32 @@ public void providerThrowsInternalAuthenticationServiceException() {
}
}

// gh-6281
@Test
public void authenticateWhenFailsInParentAndPublishesThenChildDoesNotPublish() {
BadCredentialsException badCredentialsExParent = new BadCredentialsException("Bad Credentials in parent");
ProviderManager parentMgr = new ProviderManager(
Collections.singletonList(createProviderWhichThrows(badCredentialsExParent)));
ProviderManager childMgr = new ProviderManager(Collections.singletonList(createProviderWhichThrows(
new BadCredentialsException("Bad Credentials in child"))), parentMgr);

AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class);
parentMgr.setAuthenticationEventPublisher(publisher);
childMgr.setAuthenticationEventPublisher(publisher);

final Authentication authReq = mock(Authentication.class);

try {
childMgr.authenticate(authReq);
fail("Expected exception");
}
catch (BadCredentialsException e) {
assertThat(e).isSameAs(badCredentialsExParent);
}
verify(publisher).publishAuthenticationFailure(badCredentialsExParent, authReq); // Parent publishes
verifyNoMoreInteractions(publisher); // Child should not publish (duplicate event)
}

private AuthenticationProvider createProviderWhichThrows(
final AuthenticationException e) {
AuthenticationProvider provider = mock(AuthenticationProvider.class);
Expand Down

0 comments on commit be23ab8

Please sign in to comment.