title: How to get additional user attributes from LDAP in Spring Security?
body: <p>I'm currently trying to develop a Spring Boot application whose purpose it will be to manage user entries in our LDAP directory.</p>
  
  <p>LDAP login already works; so does the lookup of groups a user is member of.</p>
  
  <p>Additionally, I'd like to populate the Spring Security <code>Principal</code> object with some more LDAP attributes of that user. I've read several posts on SO and also the official Spring documentation, but simply cannot get this to work.</p>
  
  <p>Here is my current code:
  Class <code>AuthenticationConfiguration</code></p>
  
  <pre><code>@Configuration
  class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
  
      private String ldapUrl = "ldap://127.0.0.1:10389/dc=corp,dc=org";
      private String bindUser = "cn=spring,ou=users,dc=corp,dc=org";
      private String bindPW = "&lt;password&gt;";
      private String groupSearchBase = "ou=groups";
      private String groupSearchFilter = "(member={0})";
      private String userDnPattern = "uid={0},ou=users";
      private Log log = LogFactory.getLog(this.getClass());
  
      @Override
      public void init(AuthenticationManagerBuilder auth) throws Exception {
  
          DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapUrl);
  
          contextSource.setUserDn(bindUser);
          contextSource.setPassword(bindPW);
          contextSource.afterPropertiesSet();
          log.info(contextSource.getReadOnlyContext().getAttributes("uid=testuser,ou=users")); // returns all LDAP attributes from that user
  
          DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(contextSource, groupSearchBase);
          populator.setGroupSearchFilter(groupSearchFilter);
          populator.setSearchSubtree(true);
          populator.setIgnorePartialResultException(true);
  
          auth
          .ldapAuthentication()
          .ldapAuthoritiesPopulator(populator)
          .contextSource(contextSource)
          .userDetailsContextMapper(userDetailsContextMapper())
          .userDnPatterns(userDnPattern)
          ;
      }
  
      @Bean
      public UserDetailsContextMapper userDetailsContextMapper() {
          return new CustomUserDetailsContextMapper();
      }
  
  }
  </code></pre>
  
  <p>As you can see, I'm using the userDetailsContextMapper() method to return an instance of my <code>CustomUserDetailsContextMapper</code>:</p>
  
  <pre><code>@Configuration
  public class CustomUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
  
      private Log log = LogFactory.getLog(this.getClass());
  
      @Override
      public LdapUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection&lt;? extends GrantedAuthority&gt; authorities) {
  
          LdapUserDetailsImpl details = (LdapUserDetailsImpl) super.mapUserFromContext(ctx, username, authorities);
          log.info("DN from ctx: " + ctx.getDn()); // return correct DN
          log.info("Attributes size: " + ctx.getAttributes().size()); // always returns 0
  
          return new CustomUserDetails(details);
      }
  
      @Override
      public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
          // default
      }
  }
  </code></pre>
  
  <p>Now, when you look at that first log statement in <code>AuthenticationConfiguration</code>, Spring will actually print the whole user object to stdout, correctly showing all LDAP attributes from the user:
  <code>
  {displayname=displayName: Test User, givenname=givenName: Test, objectclass=objectClass:  posixAccount, top [...]}
  </code></p>
  
  <p>However, the log statements in my <code>CustomUserDetailsContextMapper</code> class do not. Although the first one correctly displays the DN of the logged in user, <strong>the second one just display 0, i.e. ctx does not seem to contain any attributes from the current user.</strong></p>
  
  <p>I also tried directly querying for attributes via <code>ctx.getAttribute("attribute")</code>, <code>ctx.getStringAttribute("attribute")</code> or <code>ctx.getObjectAttribute("attribute")</code>, to no avail.</p>
  
  <p><strong>How can I access LDAP attributes from within the <code>mapUserFromContext</code> method?</strong></p>
  
  <p>I'm really out of ideas, so any help would be greatly appreciated :-)</p>