ActiveDirectoryLdapAuthenticationProvider uses InternalAuthenticationServiceException

Closes gh-2884
This commit is contained in:
Dávid Kovács 2020-04-19 15:29:18 +02:00 committed by Rob Winch
parent d69288e665
commit 7eee6b102f
3 changed files with 40 additions and 10 deletions

View File

@ -31,6 +31,7 @@ DigestAuthenticationFilter.usernameNotFound=Username {0} not found
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
JdbcDaoImpl.notFound=User {0} not found JdbcDaoImpl.notFound=User {0} not found
LdapAuthenticationProvider.badCredentials=Bad credentials LdapAuthenticationProvider.badCredentials=Bad credentials
LdapAuthenticationProvider.badLdapConnection=Connection to LDAP server failed
LdapAuthenticationProvider.credentialsExpired=User credentials have expired LdapAuthenticationProvider.credentialsExpired=User credentials have expired
LdapAuthenticationProvider.disabled=User is disabled LdapAuthenticationProvider.disabled=User is disabled
LdapAuthenticationProvider.expired=User account has expired LdapAuthenticationProvider.expired=User account has expired

View File

@ -16,6 +16,7 @@
package org.springframework.security.ldap.authentication.ad; package org.springframework.security.ldap.authentication.ad;
import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.support.DefaultDirObjectFactory; import org.springframework.ldap.core.support.DefaultDirObjectFactory;
@ -24,6 +25,7 @@ import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException; import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@ -141,12 +143,15 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
UsernamePasswordAuthenticationToken auth) { UsernamePasswordAuthenticationToken auth) {
String username = auth.getName(); String username = auth.getName();
String password = (String) auth.getCredentials(); String password = (String) auth.getCredentials();
DirContext ctx = null;
DirContext ctx = bindAsUser(username, password);
try { try {
ctx = bindAsUser(username, password);
return searchForUser(ctx, username); return searchForUser(ctx, username);
} }
catch (CommunicationException e) {
throw badLdapConnection(e);
}
catch (NamingException e) { catch (NamingException e) {
logger.error("Failed to locate directory entry for authenticated user: " logger.error("Failed to locate directory entry for authenticated user: "
+ username, e); + username, e);
@ -208,8 +213,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|| (e instanceof OperationNotSupportedException)) { || (e instanceof OperationNotSupportedException)) {
handleBindException(bindPrincipal, e); handleBindException(bindPrincipal, e);
throw badCredentials(e); throw badCredentials(e);
} } else {
else {
throw LdapUtils.convertLdapException(e); throw LdapUtils.convertLdapException(e);
} }
} }
@ -311,6 +315,12 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
return (BadCredentialsException) badCredentials().initCause(cause); return (BadCredentialsException) badCredentials().initCause(cause);
} }
private InternalAuthenticationServiceException badLdapConnection(Throwable cause) {
return new InternalAuthenticationServiceException(messages.getMessage(
"LdapAuthenticationProvider.badLdapConnection",
"Connection to LDAP server failed."), cause);
}
private DirContextOperations searchForUser(DirContext context, String username) private DirContextOperations searchForUser(DirContext context, String username)
throws NamingException { throws NamingException {
SearchControls searchControls = new SearchControls(); SearchControls searchControls = new SearchControls();
@ -325,6 +335,9 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
searchControls, searchRoot, searchFilter, searchControls, searchRoot, searchFilter,
new Object[] { bindPrincipal, username }); new Object[] { bindPrincipal, username });
} }
catch (CommunicationException ldapCommunicationException) {
throw badLdapConnection(ldapCommunicationException);
}
catch (IncorrectResultSizeDataAccessException incorrectResults) { catch (IncorrectResultSizeDataAccessException incorrectResults) {
// Search should never return multiple results if properly configured - just // Search should never return multiple results if properly configured - just
// rethrow // rethrow

View File

@ -32,6 +32,7 @@ import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException; import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -58,6 +59,9 @@ import static org.springframework.security.ldap.authentication.ad.ActiveDirector
* @author Rob Winch * @author Rob Winch
*/ */
public class ActiveDirectoryLdapAuthenticationProviderTests { public class ActiveDirectoryLdapAuthenticationProviderTests {
public static final String EXISTING_LDAP_PROVIDER = "ldap://192.168.1.200/";
public static final String NON_EXISTING_LDAP_PROVIDER = "ldap://192.168.1.201/";
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@ -378,17 +382,29 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
} }
@Test(expected = org.springframework.ldap.CommunicationException.class) @Test(expected = org.springframework.ldap.CommunicationException.class)
public void nonAuthenticationExceptionIsConvertedToSpringLdapException() public void nonAuthenticationExceptionIsConvertedToSpringLdapException() throws Throwable {
throws Exception { try {
provider.contextFactory = createContextFactoryThrowing(new CommunicationException( provider.contextFactory = createContextFactoryThrowing(new CommunicationException(
msg)); msg));
provider.authenticate(joe); provider.authenticate(joe);
} catch (InternalAuthenticationServiceException e) {
// Since GH-8418 ldap communication exception is wrapped into InternalAuthenticationServiceException.
// This test is about the wrapped exception, so we throw it.
throw e.getCause();
}
}
@Test(expected = org.springframework.security.authentication.InternalAuthenticationServiceException.class )
public void connectionExceptionIsWrappedInInternalException() throws Exception {
ActiveDirectoryLdapAuthenticationProvider noneReachableProvider = new ActiveDirectoryLdapAuthenticationProvider(
"mydomain.eu", NON_EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
noneReachableProvider.doAuthentication(joe);
} }
@Test @Test
public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception { public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider( ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
"mydomain.eu", "ldap://192.168.1.200/", "dc=ad,dc=eu,dc=mydomain"); "mydomain.eu", EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider); checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider);
} }