Claude
Skills
Sign in
Back

spring-ldap

Included with Lifetime
$97 forever

Spring LDAP for LDAP/Active Directory integration and authentication. Covers LdapTemplate, @Entry mapping, LdapRepository, and Spring Security integration. USE WHEN: user mentions "LDAP", "Active Directory", "AD authentication", "LdapTemplate", "@Entry", "directory services", "enterprise authentication" DO NOT USE FOR: OAuth2/OIDC - use `spring-security` or `oauth2` skill, simple auth - use Spring Security with database

Ads & Marketing

What this skill does

# Spring LDAP - Quick Reference

> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `spring-ldap` for comprehensive documentation.

## Dependencies

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
<!-- For embedded LDAP testing -->
<dependency>
    <groupId>com.unboundid</groupId>
    <artifactId>unboundid-ldapsdk</artifactId>
    <scope>test</scope>
</dependency>
```

## Configuration

### application.yml
```yaml
spring:
  ldap:
    urls: ldap://ldap.example.com:389
    base: dc=example,dc=com
    username: cn=admin,dc=example,dc=com
    password: ${LDAP_PASSWORD}

    # For Active Directory
    # urls: ldap://ad.company.com:389
    # base: dc=company,dc=com
    # username: CN=service_account,OU=Service Accounts,DC=company,DC=com

  # Embedded LDAP for development
  ldap:
    embedded:
      base-dn: dc=example,dc=com
      ldif: classpath:test-server.ldif
      port: 8389
```

## LDAP Entry Mapping

### Person Entry
```java
@Entry(base = "ou=people", objectClasses = {"person", "inetOrgPerson"})
public class Person {

    @Id
    private Name dn;

    @Attribute(name = "uid")
    private String uid;

    @Attribute(name = "cn")
    private String fullName;

    @Attribute(name = "sn")
    private String lastName;

    @Attribute(name = "givenName")
    private String firstName;

    @Attribute(name = "mail")
    private String email;

    @Attribute(name = "telephoneNumber")
    private String phone;

    @Attribute(name = "memberOf")
    private List<String> groups;

    @DnAttribute(value = "uid", index = 0)
    private String username;
}
```

### Group Entry
```java
@Entry(base = "ou=groups", objectClasses = {"groupOfNames"})
public class Group {

    @Id
    private Name dn;

    @Attribute(name = "cn")
    private String name;

    @Attribute(name = "description")
    private String description;

    @Attribute(name = "member")
    private Set<Name> members;
}
```

## Repository Pattern

```java
public interface PersonRepository extends LdapRepository<Person> {

    Person findByUid(String uid);

    List<Person> findByLastName(String lastName);

    List<Person> findByEmailContaining(String emailPart);

    @Query("(&(objectClass=person)(|(cn=*{0}*)(mail=*{0}*)))")
    List<Person> searchByNameOrEmail(String query);
}

public interface GroupRepository extends LdapRepository<Group> {

    Group findByName(String name);

    @Query("(&(objectClass=groupOfNames)(member={0}))")
    List<Group> findByMember(Name memberDn);
}
```

## LdapTemplate Operations

```java
@Service
@RequiredArgsConstructor
public class LdapService {

    private final LdapTemplate ldapTemplate;

    // Search
    public List<Person> findAllPeople() {
        return ldapTemplate.findAll(Person.class);
    }

    public Person findByDn(String dn) {
        return ldapTemplate.findByDn(LdapUtils.newLdapName(dn), Person.class);
    }

    // Search with filter
    public List<Person> searchPeople(String query) {
        LdapQuery ldapQuery = LdapQueryBuilder.query()
            .base("ou=people")
            .where("objectClass").is("person")
            .and("cn").like("*" + query + "*");

        return ldapTemplate.find(ldapQuery, Person.class);
    }

    // Create
    public void createPerson(Person person) {
        ldapTemplate.create(person);
    }

    // Update
    public void updatePerson(Person person) {
        ldapTemplate.update(person);
    }

    // Delete
    public void deletePerson(Person person) {
        ldapTemplate.delete(person);
    }

    // Bind (authenticate)
    public boolean authenticate(String username, String password) {
        LdapQuery query = LdapQueryBuilder.query()
            .where("uid").is(username);

        return ldapTemplate.authenticate(query, password);
    }
}
```

## Active Directory Integration

```java
@Configuration
public class ActiveDirectoryConfig {

    @Bean
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl("ldap://ad.company.com:389");
        contextSource.setBase("dc=company,dc=com");
        contextSource.setUserDn("CN=service_account,OU=Service Accounts,DC=company,DC=com");
        contextSource.setPassword(adPassword);
        contextSource.setReferral("follow");

        // AD specific settings
        Map<String, Object> env = new HashMap<>();
        env.put("java.naming.ldap.attributes.binary", "objectGUID");
        contextSource.setBaseEnvironmentProperties(env);

        return contextSource;
    }

    @Bean
    public LdapTemplate ldapTemplate(LdapContextSource contextSource) {
        return new LdapTemplate(contextSource);
    }
}
```

### AD User Search
```java
public List<AdUser> searchAdUsers(String query) {
    LdapQuery ldapQuery = LdapQueryBuilder.query()
        .base("OU=Users,DC=company,DC=com")
        .where("objectClass").is("user")
        .and("objectCategory").is("person")
        .and(LdapQueryBuilder.query()
            .where("sAMAccountName").like("*" + query + "*")
            .or("displayName").like("*" + query + "*")
            .or("mail").like("*" + query + "*"));

    return ldapTemplate.search(ldapQuery, new AdUserAttributesMapper());
}
```

## Spring Security Integration

```java
@Configuration
@EnableWebSecurity
public class LdapSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults())
            .ldapAuthentication(ldap -> ldap
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource(contextSource())
                .passwordCompare(password -> password
                    .passwordEncoder(new BCryptPasswordEncoder())
                    .passwordAttribute("userPassword")
                )
            );
        return http.build();
    }

    @Bean
    public LdapContextSource contextSource() {
        return new LdapContextSource() {{
            setUrl("ldap://localhost:8389");
            setBase("dc=example,dc=com");
        }};
    }
}
```

### Active Directory Authentication
```java
@Bean
public ActiveDirectoryLdapAuthenticationProvider adAuthProvider() {
    ActiveDirectoryLdapAuthenticationProvider provider =
        new ActiveDirectoryLdapAuthenticationProvider(
            "company.com",
            "ldap://ad.company.com:389",
            "dc=company,dc=com"
        );

    provider.setConvertSubErrorCodesToExceptions(true);
    provider.setUseAuthenticationRequestCredentials(true);
    provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}))");

    return provider;
}
```

## Connection Pooling

```java
@Bean
public LdapContextSource contextSource() {
    LdapContextSource contextSource = new LdapContextSource();
    contextSource.setUrl("ldap://ldap.example.com:389");
    contextSource.setBase("dc=example,dc=com");
    contextSource.setUserDn("cn=admin,dc=example,dc=com");
    contextSource.setPassword(ldapPassword);
    contextSource.setPooled(true);
    return contextSource;
}

@Bean
public PoolingContextSource poolingContextSource(LdapContextSource contextSource) {
    PoolingContextSource poolingContextSource = new PoolingContextSource();
    poolingContextSource.setContextSource(contextSource);
    poolingContextSource.setDirContextValidator(new DefaultDirContextValidator());
    poolingContextSource.setTestOnBorrow(true);
    poolingContextSource.setTestWhileIdle(true);
    return poolingContextSource;
}
```

## Testing with Embedded LDAP

### test-server.ldif
```ldif
dn: dc=example,dc=com
objectClass: top
objectClass: domain
dc: example

dn: ou=people,dc=example,dc=com
objectClass: or

Related in Ads & Marketing