/* * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap.authentication; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.*; import org.junit.Test; import org.springframework.ldap.CommunicationException; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DistinguishedName; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper; /** * Tests {@link LdapAuthenticationProvider}. * * @author Luke Taylor * @author Rob Winch * @author EddĂș MelĂ©ndez */ public class LdapAuthenticationProviderTests { // ~ Methods // ======================================================================================================== @Test public void testSupportsUsernamePasswordAuthenticationToken() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator(), new MockAuthoritiesPopulator()); assertThat(ldapProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue(); } @Test public void testDefaultMapperIsSet() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator(), new MockAuthoritiesPopulator()); assertThat(ldapProvider.getUserDetailsContextMapper() instanceof LdapUserDetailsMapper).isTrue(); } @Test public void testEmptyOrNullUserNameThrowsException() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator(), new MockAuthoritiesPopulator()); try { ldapProvider.authenticate(new UsernamePasswordAuthenticationToken(null, "password")); fail("Expected BadCredentialsException for empty username"); } catch (BadCredentialsException expected) { } try { ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("", "bobspassword")); fail("Expected BadCredentialsException for null username"); } catch (BadCredentialsException expected) { } } @Test(expected = BadCredentialsException.class) public void usernameNotFoundExceptionIsHiddenByDefault() { final LdapAuthenticator authenticator = mock(LdapAuthenticator.class); final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken( "joe", "password"); when(authenticator.authenticate(joe)).thenThrow( new UsernameNotFoundException("nobody")); LdapAuthenticationProvider provider = new LdapAuthenticationProvider( authenticator); provider.authenticate(joe); } @Test(expected = UsernameNotFoundException.class) public void usernameNotFoundExceptionIsNotHiddenIfConfigured() { final LdapAuthenticator authenticator = mock(LdapAuthenticator.class); final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken( "joe", "password"); when(authenticator.authenticate(joe)).thenThrow( new UsernameNotFoundException("nobody")); LdapAuthenticationProvider provider = new LdapAuthenticationProvider( authenticator); provider.setHideUserNotFoundExceptions(false); provider.authenticate(joe); } @Test public void normalUsage() { MockAuthoritiesPopulator populator = new MockAuthoritiesPopulator(); LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator(), populator); LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper(); userMapper.setRoleAttributes(new String[] { "ou" }); ldapProvider.setUserDetailsContextMapper(userMapper); assertThat(ldapProvider.getAuthoritiesPopulator()).isNotNull(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( "ben", "benspassword"); Object authDetails = new Object(); authRequest.setDetails(authDetails); Authentication authResult = ldapProvider.authenticate(authRequest); assertThat(authResult.getCredentials()).isEqualTo("benspassword"); assertThat(authResult.getDetails()).isSameAs(authDetails); UserDetails user = (UserDetails) authResult.getPrincipal(); assertThat(user.getAuthorities()).hasSize(2); assertThat(user.getPassword()).isEqualTo("{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); assertThat(user.getUsername()).isEqualTo("ben"); assertThat(populator.getRequestedUsername()).isEqualTo("ben"); assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) .contains("ROLE_FROM_ENTRY"); assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) .contains("ROLE_FROM_POPULATOR"); } @Test public void passwordIsSetFromUserDataIfUseAuthenticationRequestCredentialsIsFalse() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator(), new MockAuthoritiesPopulator()); ldapProvider.setUseAuthenticationRequestCredentials(false); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( "ben", "benspassword"); Authentication authResult = ldapProvider.authenticate(authRequest); assertThat(authResult.getCredentials()).isEqualTo("{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); } @Test public void useWithNullAuthoritiesPopulatorReturnsCorrectRole() { LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( new MockAuthenticator()); LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper(); userMapper.setRoleAttributes(new String[] { "ou" }); ldapProvider.setUserDetailsContextMapper(userMapper); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( "ben", "benspassword"); UserDetails user = (UserDetails) ldapProvider.authenticate(authRequest) .getPrincipal(); assertThat(user.getAuthorities()).hasSize(1); assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) .contains("ROLE_FROM_ENTRY"); } @Test public void authenticateWithNamingException() { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( "ben", "benspassword"); LdapAuthenticator mockAuthenticator = mock(LdapAuthenticator.class); CommunicationException expectedCause = new CommunicationException( new javax.naming.CommunicationException()); when(mockAuthenticator.authenticate(authRequest)).thenThrow(expectedCause); LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( mockAuthenticator); try { ldapProvider.authenticate(authRequest); fail("Expected Exception"); } catch (InternalAuthenticationServiceException success) { assertThat(success.getCause()).isSameAs(expectedCause); } } // ~ Inner Classes // ================================================================================================== class MockAuthenticator implements LdapAuthenticator { public DirContextOperations authenticate(Authentication authentication) { DirContextAdapter ctx = new DirContextAdapter(); ctx.setAttributeValue("ou", "FROM_ENTRY"); String username = authentication.getName(); String password = (String) authentication.getCredentials(); if (username.equals("ben") && password.equals("benspassword")) { ctx.setDn(new DistinguishedName( "cn=ben,ou=people,dc=springframework,dc=org")); ctx.setAttributeValue("userPassword", "{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); return ctx; } else if (username.equals("jen") && password.equals("")) { ctx.setDn(new DistinguishedName( "cn=jen,ou=people,dc=springframework,dc=org")); return ctx; } throw new BadCredentialsException("Authentication failed."); } } class MockAuthoritiesPopulator implements LdapAuthoritiesPopulator { String username; public Collection<GrantedAuthority> getGrantedAuthorities( DirContextOperations userCtx, String username) { this.username = username; return AuthorityUtils.createAuthorityList("ROLE_FROM_POPULATOR"); } String getRequestedUsername() { return username; } } }