1

If we need to get User attributes from ActiveDirectory like name, sn etc. can't we configure using Specialized LDAP authentication provider which uses Active Directory configuration conventions like "springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider"

 @Override
    protected void configure(HttpSecurity http) throws Exception {

            http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                        .authorizeRequests().antMatchers("/", "logout").permitAll().and().httpBasic();
    }


     @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception { 

            auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
        }

     @Bean
        public AuthenticationManager authenticationManager() {

         return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
        }

     @Bean
        public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {

            ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider(domain, url);
            adProvider.setConvertSubErrorCodesToExceptions(true);
            adProvider.setUseAuthenticationRequestCredentials(true);

            return adProvider;
        }

and then use AuthenticationManager like shown below.

Authentication auth = new UsernamePasswordAuthenticationToken(userName, password);
        Authentication a = authenticationManager.authenticate(auth);

But, I get a.isAuthenticated() as true for correct username and password, I also get a.getName() as my username. But, how to retrieve sn, dispalyname, name and other attributes. Do we need to write a CustomActiveDirectoryLdapAuthenticationProvider as mentioned here http://code-addict.pl/active-directory-spring-security/

likeGreen
  • 1,001
  • 1
  • 20
  • 40

1 Answers1

3

You do not. Spring Security comes with an UserDetailsContextMapper interface

/**
 * Creates a fully populated UserDetails object for use by the security framework.
 *
 * @param ctx the context object which contains the user information.
 * @param username the user's supplied login name.
 * @param authorities
 * @return the user object.
 */
UserDetails mapUserFromContext(DirContextOperations ctx, String username,
        Collection<? extends GrantedAuthority> authorities);

The default implementation, LdapUserDetailsMapper

Currently only maps the groups returned by the search.

// Map the roles
for (int i = 0; (this.roleAttributes != null)
        && (i < this.roleAttributes.length); i++) {
    String[] rolesForAttribute = ctx.getStringAttributes(this.roleAttributes[i]);

    if (rolesForAttribute == null) {
        this.logger.debug("Couldn't read role attribute '"
                + this.roleAttributes[i] + "' for user " + dn);
        continue;
    }
        for (String role : rolesForAttribute) {
        GrantedAuthority authority = createAuthority(role);
            if (authority != null) {
            essence.addAuthority(authority);
        }
    }
}

However, implementing your own UserDetailsMapper you can retrieve any and all records that come back from LDAP.

You just decide what attribute you wish to fetch

Object attribute = ctx.getObjectAttribute("some-ldap-attribute");

This is how you would fetch custom values during an authentication event.

If you want to just query and search and fetch data from the LDAP directory you can leverage the SpringSecurityLdapTemplate

It aims to mimic what RestTemplate does for HTTP but for LDAP.

Filip Hanik VMware
  • 1,484
  • 6
  • 8
  • What is ctx in your example. Is it the context containing user data. How do you set in my example. – likeGreen Jan 17 '19 at 20:07
  • 1
    [`org.springframework.ldap.core.DirContextOperations`](https://docs.spring.io/spring-ldap/site/apidocs/org/springframework/ldap/core/DirContextOperations.html) (link) is an extension to java's `javax.naming.Context` – Filip Hanik VMware Jan 17 '19 at 20:20
  • Please review the two links in the answer. – Filip Hanik VMware Jan 17 '19 at 20:21
  • Thanks @Filip. I was able to create customUserDetails by extending LdapUserDetailsImpl and use mapUserFromContext() from LdapUserDetailsMapper to map and return customUserDetails as required to get all attributes. – likeGreen Jan 18 '19 at 18:24
  • @Pan I would also like to do this. Do you have a code example? – Al Grant May 27 '19 at 08:54
  • @FilipHanikPivotal I too would like to do something similar. Is there an example somewhere? Where does Object attribute = ctx.getObjectAttribute("some-ldap-attribute"); go? – Al Grant May 27 '19 at 09:21
  • @AlGrant In the activeDirectoryLdapAuthenticationProvider() method above add – likeGreen Jun 03 '19 at 14:39
  • In the activeDirectoryLdapAuthenticationProvider() method above add adProvider.setUserDetailsContextMapper(userDetailsContextMapper()); then implement userDetailsContextMapper() method as below @Bean public UserDetailsContextMapper userDetailsContextMapper() { return new CustomUserMapper(); } Also, create a class CustomUserMapper extends extends LdapUserDetailsMapper. In the class set your values in the method mapUserFromContext() – likeGreen Jun 03 '19 at 14:45
  • How to get the Object attribute = ctx.getObjectAttribute("some-ldap-attribute"); values in the controller? For example I want to retrieve employee ID from the ldap attribute and display employee ID of the logged in user in UI. – vrh Feb 04 '21 at 09:18