|
@@ -23,7 +23,7 @@ import java.util.Arrays;
|
|
|
import java.util.List;
|
|
|
|
|
|
import org.junit.Test;
|
|
|
-import org.springframework.security.MockApplicationEventPublisher;
|
|
|
+import org.springframework.context.MessageSource;
|
|
|
import org.springframework.security.authentication.AuthenticationProvider;
|
|
|
import org.springframework.security.authentication.ProviderManager;
|
|
|
import org.springframework.security.authentication.ProviderNotFoundException;
|
|
@@ -31,7 +31,6 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
|
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
|
import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
|
|
|
import org.springframework.security.authentication.concurrent.ConcurrentSessionController;
|
|
|
-import org.springframework.security.authentication.concurrent.NullConcurrentSessionController;
|
|
|
import org.springframework.security.core.Authentication;
|
|
|
import org.springframework.security.core.AuthenticationException;
|
|
|
import org.springframework.security.core.GrantedAuthority;
|
|
@@ -43,6 +42,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|
|
* @author Ben Alex
|
|
|
* @version $Id$
|
|
|
*/
|
|
|
+@SuppressWarnings("unchecked")
|
|
|
public class ProviderManagerTests {
|
|
|
|
|
|
@Test(expected=ProviderNotFoundException.class)
|
|
@@ -51,46 +51,34 @@ public class ProviderManagerTests {
|
|
|
AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
|
|
|
|
|
|
ProviderManager mgr = makeProviderManager();
|
|
|
- mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
+ mgr.setMessageSource(mock(MessageSource.class));
|
|
|
mgr.authenticate(token);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
public void authenticationSucceedsWithSupportedTokenAndReturnsExpectedObject() throws Exception {
|
|
|
- TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password","ROLE_ONE","ROLE_TWO");
|
|
|
-
|
|
|
- ProviderManager mgr = makeProviderManager();
|
|
|
- mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
-
|
|
|
- Authentication result = mgr.authenticate(token);
|
|
|
-
|
|
|
- if (!(result instanceof TestingAuthenticationToken)) {
|
|
|
- fail("Should have returned instance of TestingAuthenticationToken");
|
|
|
- }
|
|
|
+ final Authentication a = mock(Authentication.class);
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class);
|
|
|
+ mgr.setAuthenticationEventPublisher(publisher);
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichReturns(a)));
|
|
|
|
|
|
- TestingAuthenticationToken castResult = (TestingAuthenticationToken) result;
|
|
|
- assertEquals("Test", castResult.getPrincipal());
|
|
|
- assertEquals("Password", castResult.getCredentials());
|
|
|
- assertEquals(AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"), castResult.getAuthorities());
|
|
|
+ Authentication result = mgr.authenticate(a);
|
|
|
+ assertEquals(a, result);
|
|
|
+ verify(publisher).publishAuthenticationSuccess(result);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void authenticationSuccessWhenFirstProviderReturnsNullButSecondAuthenticates() {
|
|
|
- TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password","ROLE_ONE","ROLE_TWO");
|
|
|
- ProviderManager mgr = makeProviderManagerWithMockProviderWhichReturnsNullInList();
|
|
|
- mgr.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
-
|
|
|
- Authentication result = mgr.authenticate(token);
|
|
|
-
|
|
|
- if (!(result instanceof TestingAuthenticationToken)) {
|
|
|
- fail("Should have returned instance of TestingAuthenticationToken");
|
|
|
- }
|
|
|
+ public void authenticationSucceedsWhenFirstProviderReturnsNullButSecondAuthenticates() {
|
|
|
+ final Authentication a = mock(Authentication.class);
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class);
|
|
|
+ mgr.setAuthenticationEventPublisher(publisher);
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichReturns(null), createProviderWhichReturns(a)));
|
|
|
|
|
|
- TestingAuthenticationToken castResult = (TestingAuthenticationToken) result;
|
|
|
- assertEquals("Test", castResult.getPrincipal());
|
|
|
- assertEquals("Password", castResult.getCredentials());
|
|
|
- assertEquals("ROLE_ONE", castResult.getAuthorities().get(0).getAuthority());
|
|
|
- assertEquals("ROLE_TWO", castResult.getAuthorities().get(1).getAuthority());
|
|
|
+ Authentication result = mgr.authenticate(a);
|
|
|
+ assertSame(a, result);
|
|
|
+ verify(publisher).publishAuthenticationSuccess(result);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -99,11 +87,10 @@ public class ProviderManagerTests {
|
|
|
|
|
|
//The NullConcurrentSessionController should be the default
|
|
|
assertNotNull(target.getSessionController());
|
|
|
- assertTrue(target.getSessionController() instanceof NullConcurrentSessionController);
|
|
|
|
|
|
ConcurrentSessionController csc = mock(ConcurrentSessionController.class);
|
|
|
target.setSessionController(csc);
|
|
|
- assertEquals(csc, target.getSessionController());
|
|
|
+ assertSame(csc, target.getSessionController());
|
|
|
}
|
|
|
|
|
|
@Test(expected=IllegalArgumentException.class)
|
|
@@ -119,8 +106,6 @@ public class ProviderManagerTests {
|
|
|
@Test(expected=IllegalArgumentException.class)
|
|
|
public void getProvidersFailsIfProviderListNotSet() throws Exception {
|
|
|
ProviderManager mgr = new ProviderManager();
|
|
|
-
|
|
|
- mgr.afterPropertiesSet();
|
|
|
mgr.getProviders();
|
|
|
}
|
|
|
|
|
@@ -137,6 +122,7 @@ public class ProviderManagerTests {
|
|
|
final Object resultDetails = "(Result Details)";
|
|
|
ProviderManager authMgr = makeProviderManager();
|
|
|
|
|
|
+ // A provider which sets the details object
|
|
|
AuthenticationProvider provider = new AuthenticationProvider() {
|
|
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
|
|
((TestingAuthenticationToken)authentication).setDetails(resultDetails);
|
|
@@ -166,25 +152,53 @@ public class ProviderManagerTests {
|
|
|
request.setDetails(details);
|
|
|
|
|
|
Authentication result = authMgr.authenticate(request);
|
|
|
- assertEquals(details, result.getDetails());
|
|
|
+ assertSame(details, result.getDetails());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void authenticationExceptionIsIgnoredIfLaterProviderAuthenticates() throws Exception {
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ final Authentication authReq = mock(Authentication.class);
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichThrows(new BadCredentialsException("")),
|
|
|
+ createProviderWhichReturns(authReq)));
|
|
|
+ assertSame(authReq, mgr.authenticate(mock(Authentication.class)));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void authenticationExceptionIsRethrownIfNoLaterProviderAuthenticates() throws Exception {
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichThrows(new BadCredentialsException("")),
|
|
|
+ createProviderWhichReturns(null)));
|
|
|
+ try {
|
|
|
+ mgr.authenticate(mock(Authentication.class));
|
|
|
+ fail("Expected BadCredentialsException");
|
|
|
+ } catch (BadCredentialsException expected) {
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// SEC-546
|
|
|
- @Test(expected=AccountStatusException.class)
|
|
|
+ @Test
|
|
|
public void accountStatusExceptionPreventsCallsToSubsequentProviders() throws Exception {
|
|
|
ProviderManager authMgr = makeProviderManager();
|
|
|
+ AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows(new AccountStatusException(""){});
|
|
|
+ AuthenticationProvider otherProvider = mock(AuthenticationProvider.class);
|
|
|
|
|
|
- authMgr.setProviders(Arrays.asList(new MockProviderWhichThrowsAccountStatusException(),
|
|
|
- new MockProviderWhichThrowsConcurrentLoginException()) );
|
|
|
+ authMgr.setProviders(Arrays.asList(iThrowAccountStatusException, otherProvider));
|
|
|
|
|
|
- authMgr.authenticate(createAuthenticationToken());
|
|
|
+ try {
|
|
|
+ authMgr.authenticate(mock(Authentication.class));
|
|
|
+ fail("Expected AccountStatusException");
|
|
|
+ } catch (AccountStatusException expected) {
|
|
|
+ }
|
|
|
+ verifyZeroInteractions(otherProvider);
|
|
|
}
|
|
|
|
|
|
@Test(expected=ConcurrentLoginException.class)
|
|
|
public void concurrentLoginExceptionPreventsCallsToSubsequentProviders() throws Exception {
|
|
|
ProviderManager authMgr = makeProviderManager();
|
|
|
- // Two providers so if the second is polled it will throw an AccountStatusException
|
|
|
- authMgr.setProviders(Arrays.asList(new MockProvider(), new MockProviderWhichThrowsAccountStatusException()) );
|
|
|
+ // Two providers so if the second is polled it will throw an BadCredentialsException
|
|
|
+ authMgr.setProviders(Arrays.asList(new MockProvider(), createProviderWhichThrows(new BadCredentialsException(""))) );
|
|
|
TestingAuthenticationToken request = createAuthenticationToken();
|
|
|
ConcurrentSessionController ctrlr = mock(ConcurrentSessionController.class);
|
|
|
doThrow(new ConcurrentLoginException("mocked")).when(ctrlr).checkAuthenticationAllowed(request);
|
|
@@ -193,29 +207,96 @@ public class ProviderManagerTests {
|
|
|
authMgr.authenticate(request);
|
|
|
}
|
|
|
|
|
|
- private TestingAuthenticationToken createAuthenticationToken() {
|
|
|
- return new TestingAuthenticationToken("name", "password", new ArrayList<GrantedAuthority>(0));
|
|
|
+ @Test
|
|
|
+ public void parentAuthenticationIsUsedIfProvidersDontAuthenticate() throws Exception {
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ mgr.setProviders(Arrays.asList(mock(AuthenticationProvider.class)));
|
|
|
+ Authentication authReq = mock(Authentication.class);
|
|
|
+ AuthenticationManager parent = mock(AuthenticationManager.class);
|
|
|
+ when(parent.authenticate(authReq)).thenReturn(authReq);
|
|
|
+ mgr.setParent(parent);
|
|
|
+ assertSame(authReq, mgr.authenticate(authReq));
|
|
|
}
|
|
|
|
|
|
- private ProviderManager makeProviderManager() throws Exception {
|
|
|
- MockProvider provider1 = new MockProvider();
|
|
|
- List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>();
|
|
|
- providers.add(provider1);
|
|
|
+ @Test
|
|
|
+ public void parentIsNotCalledIfAccountStatusExceptionIsThrown() throws Exception {
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows(new AccountStatusException(""){});
|
|
|
+ mgr.setProviders(Arrays.asList(iThrowAccountStatusException));
|
|
|
+ AuthenticationManager parent = mock(AuthenticationManager.class);
|
|
|
+ mgr.setParent(parent);
|
|
|
+ try {
|
|
|
+ mgr.authenticate(mock(Authentication.class));
|
|
|
+ fail("Expected exception");
|
|
|
+ } catch (AccountStatusException expected) {
|
|
|
+ }
|
|
|
+ verifyZeroInteractions(parent);
|
|
|
+ }
|
|
|
|
|
|
+ @Test
|
|
|
+ public void providerNotFoundFromParentIsIgnored() throws Exception {
|
|
|
ProviderManager mgr = new ProviderManager();
|
|
|
- mgr.setProviders(providers);
|
|
|
+ final Authentication authReq = mock(Authentication.class);
|
|
|
+ AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class);
|
|
|
+ mgr.setAuthenticationEventPublisher(publisher);
|
|
|
+ // Set a provider that throws an exception - this is the exception we expect to be propagated
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichThrows(new BadCredentialsException(""))));
|
|
|
+ AuthenticationManager parent = mock(AuthenticationManager.class);
|
|
|
+ when(parent.authenticate(authReq)).thenThrow(new ProviderNotFoundException(""));
|
|
|
+ mgr.setParent(parent);
|
|
|
+ try {
|
|
|
+ mgr.authenticate(authReq);
|
|
|
+ fail("Expected exception");
|
|
|
+ } catch (BadCredentialsException expected) {
|
|
|
+ verify(publisher).publishAuthenticationFailure(expected, authReq);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- mgr.afterPropertiesSet();
|
|
|
+ @Test
|
|
|
+ public void authenticationExceptionFromParentOverridesPreviousOnes() throws Exception {
|
|
|
+ ProviderManager mgr = new ProviderManager();
|
|
|
+ final Authentication authReq = mock(Authentication.class);
|
|
|
+ AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class);
|
|
|
+ mgr.setAuthenticationEventPublisher(publisher);
|
|
|
+ // Set a provider that throws an exception - this is the exception we expect to be propagated
|
|
|
+ final BadCredentialsException expected = new BadCredentialsException("I'm the one from the parent");
|
|
|
+ mgr.setProviders(Arrays.asList(createProviderWhichThrows(new BadCredentialsException(""))));
|
|
|
+ AuthenticationManager parent = mock(AuthenticationManager.class);
|
|
|
+ when(parent.authenticate(authReq)).thenThrow(expected);
|
|
|
+ mgr.setParent(parent);
|
|
|
+ try {
|
|
|
+ mgr.authenticate(authReq);
|
|
|
+ fail("Expected exception");
|
|
|
+ } catch (BadCredentialsException e) {
|
|
|
+ assertSame(expected, e);
|
|
|
+ }
|
|
|
+ verify(publisher).publishAuthenticationFailure(expected, authReq);
|
|
|
+ }
|
|
|
|
|
|
- return mgr;
|
|
|
+ private AuthenticationProvider createProviderWhichThrows(final AuthenticationException e) {
|
|
|
+ AuthenticationProvider provider = mock(AuthenticationProvider.class);
|
|
|
+ when(provider.supports(any(Class.class))).thenReturn(true);
|
|
|
+ when(provider.authenticate(any(Authentication.class))).thenThrow(e);
|
|
|
+
|
|
|
+ return provider;
|
|
|
}
|
|
|
|
|
|
- private ProviderManager makeProviderManagerWithMockProviderWhichReturnsNullInList() {
|
|
|
- MockProviderWhichReturnsNull provider1 = new MockProviderWhichReturnsNull();
|
|
|
- MockProvider provider2 = new MockProvider();
|
|
|
- List<Object> providers = new ArrayList<Object>();
|
|
|
+ private AuthenticationProvider createProviderWhichReturns(final Authentication a) {
|
|
|
+ AuthenticationProvider provider = mock(AuthenticationProvider.class);
|
|
|
+ when(provider.supports(any(Class.class))).thenReturn(true);
|
|
|
+ when(provider.authenticate(any(Authentication.class))).thenReturn(a);
|
|
|
+
|
|
|
+ return provider;
|
|
|
+ }
|
|
|
+
|
|
|
+ private TestingAuthenticationToken createAuthenticationToken() {
|
|
|
+ return new TestingAuthenticationToken("name", "password", new ArrayList<GrantedAuthority>(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ private ProviderManager makeProviderManager() throws Exception {
|
|
|
+ MockProvider provider1 = new MockProvider();
|
|
|
+ List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>();
|
|
|
providers.add(provider1);
|
|
|
- providers.add(provider2);
|
|
|
|
|
|
ProviderManager mgr = new ProviderManager();
|
|
|
mgr.setProviders(providers);
|
|
@@ -242,43 +323,4 @@ public class ProviderManagerTests {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- private class MockProviderWhichReturnsNull implements AuthenticationProvider {
|
|
|
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
|
|
- if (supports(authentication.getClass())) {
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- throw new AuthenticationServiceException("Don't support this class");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(Class<? extends Object> authentication) {
|
|
|
- if (TestingAuthenticationToken.class.isAssignableFrom(authentication)) {
|
|
|
- return true;
|
|
|
- } else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private class MockProviderWhichThrowsAccountStatusException implements AuthenticationProvider {
|
|
|
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
|
|
- throw new AccountStatusException("xxx") {};
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(Class<? extends Object> authentication) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private class MockProviderWhichThrowsConcurrentLoginException implements AuthenticationProvider {
|
|
|
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
|
|
- throw new ConcurrentLoginException("xxx") {};
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(Class<? extends Object> authentication) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
}
|