User LDAP to login Users

Greetings,

I want to connect my Vaadin program to ldap to authenticate users I followed the guide on How to set up spring login in Hilla apps | Vaadin

And my SecurityConfig looks exactly like the Code from the Guide:

import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity // <1>
@Configuration
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig { // <2>


  @Bean
  public SecurityFilterChain vaadinSecurityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(auth ->
        auth.requestMatchers(HttpMethod.GET, "/images/*.png").permitAll());  // <3>
    http.with(vaadin(), vaadin -> vaadin.loginView(LoginView.class)); // <4>
    return http.build();
  }
  @Bean
  public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
    return EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
  }

  @Bean
  AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource, LdapAuthoritiesPopulator authorities) {
    LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
        contextSource, NoOpPasswordEncoder.getInstance());
    factory.setUserDnPatterns("uid={0},ou=people");
    factory.setUserSearchBase("ou=people");
    factory.setPasswordAttribute("userPassword");
    factory.setLdapAuthoritiesPopulator(authorities);
    return factory.createAuthenticationManager();
  }

  @Bean
  LdapAuthoritiesPopulator authorities(BaseLdapPathContextSource contextSource) {
    String groupSearchBase = "ou=groups";
    DefaultLdapAuthoritiesPopulator authorities =
        new DefaultLdapAuthoritiesPopulator(contextSource, groupSearchBase);
    authorities.setGroupSearchFilter("member={0}");
    return authorities;
  }

  

}

I also imported

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

But neither Intelij nor maven can detect the LdapAuthoritiesPopulator and I get the error:
Cannot resolve symbol ‘LdapAuthoritiesPopulator’

What am I doing wrong? Or how do I can authenticate user via ldap?

Make sure to follow the official spring guide. LDAP Authentication :: Spring Security

1 Like

Hi,

I don’t know those LdapAuthoritiesPopulator, but here is my version of the SecurityConfig I usually use in projects where LDAP/ActiveDirectory authentication is needed.

I distinguish between PROD and DEVEL profile: for PROD I take the real ActiveDirectory from the customers infrastructure using config values from the application.yml

${spring.ldap.urls}, ${spring.ldap.domain}, ${spring.ldap.base}")

But on default profile at DEVEL I use the Embedded UnboundID Server with users / roles from local embedded-ldap.ldif

@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings("deprecation")
public class SecurityConfig extends VaadinWebSecurity {

    public static final String ROLE_PREFIX = "ROLE_";
    public static final String LOGOUT_SUCCESS_URL = "/login"; 

    @Value("${spring.ldap.urls}")
    String ldapUrl;

    @Value("${spring.ldap.domain}")
    String ldapDomain;

    @Value("${spring.ldap.base}")
    String baseDN;

    // deps
    private final EmployeeService employeeService;
    private final ApplicationContext springContext;

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

        http.logout(customizer -> customizer
            .logoutUrl("/noUser") 
            .invalidateHttpSession(true)); 

        super.configure(http);
        this.setLoginView(http, LoginView.class, LOGOUT_SUCCESS_URL);

        http.formLogin(customizer -> customizer
            .failureHandler(new SimpleUrlAuthenticationFailureHandler("/noUser"))
        );
    }

    @Bean
    @Profile({"prod", "demo_prod"})
    public AuthenticationManager prodAuthManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.authenticationProvider(activeDirectoryProvider());
        return authenticationManagerBuilder.build();
    }

    @Bean
    @Profile( {"default"})
    public AuthenticationManager nonProdAuthMananger(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        var intermediate = dummyLdapConfigurer(authenticationManagerBuilder).and();
        return intermediate.build();
    }

    private AuthenticationProvider activeDirectoryProvider() {
        ActiveDirectoryLdapAuthenticationProvider authProvider = new ActiveDirectoryLdapAuthenticationProvider(this.ldapDomain, this.ldapUrl, this.baseDN);
        authProvider.supports(UsernamePasswordAuthenticationToken.class);
        authProvider.setConvertSubErrorCodesToExceptions(true);
        authProvider.setUseAuthenticationRequestCredentials(true);
        return authProvider;
    }

    // using users from embedded-ldap.ldif
    private LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> dummyLdapConfigurer(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        return authenticationManagerBuilder
            .ldapAuthentication()
            .userDnPatterns("uid={0},ou=people")
            .groupSearchBase("ou=groups")
            .contextSource()
            .url("ldap://localhost:8389/dc=springframework,dc=org")
            .and()
            .passwordCompare()
            .passwordEncoder(new BCryptPasswordEncoder())
            .passwordAttribute("userPassword")
            .and();
    }
}

I need different values for ldap.domain and ldap.base because they are different for my customers setup. They changed the AciveDirectory setup over night and doesn’t inform me … it took me 2 days to find out why the login doesn’t work any longer and what to fix :see_no_evil:

Hope that helps
Kind regards
1 Like

This sounds like a classpath or dependency resolution issue; either you’re missing some dependency you need for that one or it’s not being picked up by the IDE/build.

This is the .jar where the file is located (version number at the end may vary)

1 Like

Thanks a lot… I had to download the source manually and now the IDE recognizes the dependency.