Skip to content

Instantly share code, notes, and snippets.

@gclaussn
Last active January 4, 2024 17:10
Show Gist options
  • Save gclaussn/7868e6fbe7f028306af0b910cd3a56dc to your computer and use it in GitHub Desktop.
Save gclaussn/7868e6fbe7f028306af0b910cd3a56dc to your computer and use it in GitHub Desktop.
Spring Boot - Web security configuration with LDAP

Add Maven dependencies:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-ldap</artifactId>
</dependency>

Create configuration by extending the WebSecurityConfigurerAdapter class:

@Configuration
@EnableWebSecurity
@Profile("prd")
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Value("${ldap.url}")
  protected String ldapUrl;
  @Value("${ldap.manager.dn}")
  protected String ldapManagerDn;
  @Value("${ldap.manager.password}")
  protected String ldapManagerPassword;

  @Bean
  public LdapContextSource ldapContextSource() {
    LdapContextSource ldapContextSource = new LdapContextSource();
    ldapContextSource.setUrl(ldapUrl);
    ldapContextSource.setUserDn(ldapManagerDn);
    ldapContextSource.setPassword(ldapManagerPassword);
    ldapContextSource.afterPropertiesSet();
    
    return ldapContextSource;
  }
  
  @Bean
  public LdapTemplate ldapTemplate(LdapContextSource ldapContextSource) {
     return new LdapTemplate(ldapContextSource);
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeRequests()
      .antMatchers("/webjars/**").permitAll()
      .antMatchers("/app.css").permitAll()
      .anyRequest().authenticated()
      .and()
      .httpBasic()
      .and()
      .formLogin()
      .loginPage("/login").defaultSuccessUrl("/").permitAll()
      .and()
      .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.ldapAuthentication()
      .userDetailsContextMapper(new CustomLdapUserDetailsMapper())
      .userSearchFilter("(uid={0})")
      .contextSource()
      .url(ldapUrl)
      .managerDn(ldapManagerDn)
      .managerPassword(ldapManagerPassword);
  }
}

Use profiles to provide an implementation for local development, which lets you act as an "anonymousUser":

http
  .csrf().disable()
  .authorizeRequests()
  .antMatchers("/")
  .permitAll();

Use a custom LDAP user details mapper to map specific attributes:

public class CustomLdapUserDetailsMapper extends LdapUserDetailsMapper {

  private static final Logger LOGGER = LoggerFactory.getLogger(CustomLdapUserDetailsMapper.class);

  @Override
  public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
    UserDetails userDetails = super.mapUserFromContext(ctx, username, authorities));
    
    // Wrap user details
    // ctx.getStringAttribute("title")

    return wrappedUserDetails;
  }
}

LADAP properties:

ldap.url=ldap://<host>:389/ou=y,o=z
ldap.manager.dn=uid=u,ou=x,ou=y,o=z
ldap.manager.password=...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment