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
.