As a workaround I implementend a custom AuthenticationProvider and a custom UserDetailsContextMapper.
Becouse ActiveDirectoryLdapAuthenticationProvider is a final class I implemented the ADCustomAuthenticationProvider via composition, this way:
public class ADCustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private ActiveDirectoryLdapAuthenticationProvider adAuthProvider;
@Autowired
private UserDao uDao;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String principal = authentication.getPrincipal().toString();
String username = principal.split("@")[0];
User utente = uDao.findByUsername(username);
if (utente == null) {
throw new ADUnregisteredUserAuthenticationException("user ["
+ principal + "] is not registered");
}
return adAuthProvider.authenticate(authentication);
}
@Override
public boolean supports(Class<?> authentication) {
return adAuthProvider.supports(authentication);
}
}
In the mapper I extended LdapUserDetailsMapper implementing only mapUserFromContext method.
public class ADCustomUserDetailsContextMapper extends LdapUserDetailsMapper {
@Autowired
private UserDetailsService userDetailsService; // ... the service used for DB authentication
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx,
String username, Collection<? extends GrantedAuthority> authorities) {
return userDetailsService.loadUserByUsername(username);
}
}
(I'll probably need to implement mapUserToContext method beacuse I'm using a custom UserDetails implementation that not extends LdapUserDetails, so the reverse convertion process could throw an exception...)
NOTE This way I'm repeating the same query (to Users table) two times... I'd like to find a way to make a single query and share the result among AuthenticationProvider and UserDetailsContextMapper.e result among AuthenticationProvider and UserDetailsContextMapper.