0
votes

I am trying to integrate LDAP authentication for my Spring MVC app. The users are successfully able to log in, if I set the contextSource to a dummy user DN and respective password. What I want to do is to be able to bind the ldap connection without using the dummy user.

Here's the code of what works -

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http

            .authorizeRequests()
                .antMatchers("/css/**").permitAll()
                .antMatchers("/","/login**").permitAll()
                .antMatchers("/home_vm","/details/**").authenticated() 
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .defaultSuccessUrl("/home_vm", true)
                .and()
            .logout()
                .permitAll();

        http.headers().httpStrictTransportSecurity();

    }

    @Configuration
    @Profile({"default", "opt_ad_auth"})
    protected static class ActiveDirectoryAuthenticationConfiguration extends
            GlobalAuthenticationConfigurerAdapter {
        @Value("${app.ldap.url}")
        private String ldapURL;
        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {


             DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURL);

           contextSource.setUserDn("cn=Dummy User,cn=Users,dc=somecompany,dc=com");



              contextSource.setPassword("mypassword");

            contextSource.setReferral("follow"); 

            contextSource.afterPropertiesSet();



                auth.ldapAuthentication()

                .userSearchFilter("(sAMAccountName={0})")

                    .contextSource(contextSource)
                    ;

        }
    }   
}

Now I have tried to remove the hardcoded userDn and password (updated init())-

public void init(AuthenticationManagerBuilder auth) throws Exception {   
                auth.ldapAuthentication()
                .userSearchFilter("(sAMAccountName={0})")
                .contextSource()
                .url(ldapURL)
                    ;
        }
    }

The app starts fine, but I get exception - "a successful bind must be completed on the connection".

Stacktrace -

org.springframework.security.authentication.InternalAuthenticationServiceException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1

[UPDATE] I have modified the init method to the following to more closely follow the spring tutorial(https://spring.io/guides/gs/authenticating-ldap/) -

public void init(AuthenticationManagerBuilder auth) throws Exception {

        auth.ldapAuthentication()
        .userDnPatterns("sAMAccountName={0}")
        .contextSource().url(ldapURL)
            ;

}

I don't get the before-mentioned bind exception, but still not able to authenticate. Bad credentials.

2

2 Answers

0
votes

You need to do this in two steps:

  1. Bind to LDAP as an administrative user that has enough privileges to search the tree and find the user via whatever unique information you have about him.
  2. Rebind to LDAP as the found user's DN using the supplied password.
  3. Disconnect.

If all that succeeds, the username existed and the password was correct. If there was any failure you should treat it as a loging failure. Specifically, you should not tell the user whether it was the username not being found or the password being incorrect that was the reason for the failure: this is an information leak to an attacer.

-1
votes

You can authenticate with LDAP in 2 forms:

You can make a bind with the complete DN of the user (full path in the LDAP tree) and the password.

Or you can bind to LDAP as a superuser that can search on all the LDAP tree. The LDAP authenticator finds the user DN and compare the user password with the password in the user entry.

In your first code you use the second system. You need a user that can bind on the LDAP and find the user entry.

If you want user the second system, you must supply the complete DN of the user entry not the uid only.