3
votes

I am working in a Spring MVC Thymeleaf project where LDAP security with Database and Role-based granted authorities is a must-have requirement from the end-user.

What I need

  • Primary authentication should be performed by LDAP
  • User Role and granted authorities must be configured in the database along with LDAP user name
example: 
LDAP user: [email protected]
Role: Admin
Granted Authorities for "Admin" role: permission_x,permission_y etc

Which will be used in web page as "hasAuthority("permission_x")"

  • After LDAP Authentication, System will check if User Exist in the database as a white list user
  • After the white list check, roles and privileges will be loaded for the user and authorization will be imposed for loaded permissions(not role)

What I found is here:

Now my questions are:

  1. Do I need to store LDAP Password with LDAP user Name? If yes, is it safe?
  2. Is there any example that exists for the above scenario?
  3. Will fine-grained granted authorities work for LDAP users?

How LDAP authentication and jdbc based authorization will work together? Can anybody help?

Thanks in advance

1

1 Answers

5
votes

Since I have found a solution, I am sharing my own answer here. Hope it will help others:

My Answers are:

  1. No Password needs to be stored in the database.
  2. Not exactly
  3. Yes, fine-grained granted authority works perfectly for LDAP users

How I solved my problem:

Step 1:

The trick is using a UserDetailsContextMapper with UserDetails provided by regular UserDetailsService.

example:

 @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .ldapAuthentication()
                .userDetailsContextMapper(userDetailsContextMapper())
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource()
                .url("ldap://localhost:8389/dc=springframework,dc=org")
                .and()
                .passwordCompare()
                .passwordEncoder(new BCryptPasswordEncoder())
                .passwordAttribute("userPassword");
    }


 @Bean
    public UserDetailsContextMapper userDetailsContextMapper() {
        return new LdapUserDetailsMapper() {
            @Override
            public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
                UserDetails details= userDetailsService.loadUserByUsername(username+"@test.com");
                return  details;
            }
        };
    }

After successful LDAP authentication, it will try to load valid registered user to the context with all granted authorities.

Step 2

hasAuthority didn't work for me. I have used something like below:

<div sec:authorize="hasRole('SOME_PRIVILEGE')">
            <div class="alert alert-success" role="alert">
                This is secret DIV
            </div>
        </div>

For a quick check, you can use below:

<span sec:authentication="principal.authorities"></span>

I hope it will help somebody someday.

Happy Coding!

Edit: For LDAP over SSL and Spring Boot