Question

I am trying to enable both JDBA and Active Directory Authentication , i made great progress but currently i am stuck as userDetailsService is trying to compare the password in LdapUserDetails which does not exist . When checking the log i see it is able to query the user and authenticate and get the roles correctly.

I know i should use bindService or so , but i couldn't find till now how to do that.

Below is what i did .

in WebSecurityConfigurerAdapter

@Autowired
public void configureGlobal(UserDetailsService userDetailsService,UserLdapRepositoryUserDetailsService userLdapRepositoryUserDetailsService,AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userDetailsService).
    and()
        .userDetailsService(userLdapRepositoryUserDetailsService);
}

For LDAP Configuration

    @Bean
public BaseLdapPathContextSource contextSource() {
    DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://XXXXX:389/dc=XXXXXX,dc=co");
    //contextSource.setUserDn("CN=Ali Shahbour,OU=Users,DC=XXXXXXX,DC=co");
    contextSource.setUserDn("XXXXXX");
    contextSource.setPassword("XXXXXX");
    return contextSource;
}

@Bean
@Autowired
public LdapUserSearch userSearch(BaseLdapPathContextSource contextSource) { 
    FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("", "(uid={0})", contextSource);
    return userSearch;
}

@Bean 
@Autowired
public LdapAuthoritiesPopulator authoritiesPopulator(BaseLdapPathContextSource contextSource) {

    DefaultLdapAuthoritiesPopulator authoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource, "OU=CDRMonitor");

    authoritiesPopulator.setGroupSearchFilter("(member={0})");
    //authoritiesPopulator.setRolePrefix("ROLE");
    authoritiesPopulator.setSearchSubtree(true);
    //authoritiesPopulator.setConvertToUpperCase(true);

    return authoritiesPopulator;
}

As for the LdapUserDetailsService

@Service("userLdapRepositoryUserDetailsService")
public class UserLdapRepositoryUserDetailsService extends LdapUserDetailsService {

private final UserRepository userRepository;

@Autowired
public UserLdapRepositoryUserDetailsService(LdapUserSearch userSearch,
        LdapAuthoritiesPopulator authoritiesPopulator,UserRepository userRepository) {
    super(userSearch, authoritiesPopulator);
    this.userRepository = userRepository;


}

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {
    UserDetails userDetails = super.loadUserByUsername(username);
    //User user = userRepository.findByEmail(username);
    User user = new User();
    return new LdapUserRepositoryUserDetails(user, userDetails);
}

@Override
public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) {
    super.setUserDetailsMapper(userDetailsMapper);
}

private final static class LdapUserRepositoryUserDetails extends User implements LdapUserDetails {

    private final LdapUserDetailsImpl ldapUserDetailsImpl;

    private LdapUserRepositoryUserDetails(User user,UserDetails userDetails) {
        super(user);
        ldapUserDetailsImpl = (LdapUserDetailsImpl) userDetails;
    }

    private static final long serialVersionUID = 5639683223516504866L;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return ldapUserDetailsImpl.getAuthorities();
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return ldapUserDetailsImpl.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return ldapUserDetailsImpl.isAccountNonExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return ldapUserDetailsImpl.isAccountNonLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return ldapUserDetailsImpl.isCredentialsNonExpired();
    }

    @Override
    public boolean isEnabled() {
        return ldapUserDetailsImpl.isEnabled();
    }

    @Override
    public String getDn() {
        return ldapUserDetailsImpl.getDn();
    }
}

}

Was it helpful?

Solution

LDAP and SQL in an authentication context are in general not used together, because LDAP BIND authentication sends the password to the LDAP server instead of retrieving a hash value of the password.

The intended procedure of LDAP Authentication is as follows:

  • Usually a spring security UsernamePassword filter is used to pick up the credentials and is active by default. e.g. if you us a login form, when submitting the form, this filter picks up the credentials.
  • Next an LDAP Authentication Provider performs a login (LDAPBindAuthenticator) against the LDAP server (LDAP ContextSource) to verify the credentials.
  • If the login is successful, the LDAP Authentication Provider searches the LDAP for a user entry. This can be customised by providing a 'usersearch' spring bean.
  • If the user entry is found, the LDAP Authority mapper will map attributes of the user entry to groups/roles in spring security. By default this are all OU attributes
  • Lastly a new authentication object is made with the username and retrieved groups from the LDAP.

How to integrate LDAP Authentication using Spring XML is explained here. http://docs.spring.io/spring-security/site/docs/3.1.x/reference/ldap.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top