Active Directory example with login based on filtering users by roles

In this example, we'll see an Active Directory connection that allows connecting any Active Directory authenticated user member of ROLE_USER or ROLE_ADMIN.

LDAP structure

dc=com
    dc=company
        ou=OPENKM
            cn=ROLE_ADMIN
                member=okmAdmin
                member=user1
            cn=ROLE_USER
                member=user3
            cn=ROLE_XXXX
                member=user2
            cn=ROLE_YYYY
                member=user4
                ...
        ou=organization1
            sAMAccountName=okmAdmin
                memberOf=CN=ROLE_ADMIN,OU=OPENKM,DC=company,DC=com
                userPrincipalName=okmAdmin@mail.com
                cn=OpenKM Administrator
            sAMAccountName=user1
                memberOf=CN=ROLE_ADMIN,OU=OPENKM,DC=company,DC=com
                userPrincipalName=user1@mail.com
                cn=User Name 1
            sAMAccountName=user2
                memberOf=CN=ROLE_XXXX,OU=OPENKM,DC=company,DC=com
                userPrincipalName=user2@mail.com
                cn=User Name 3
        ou=organization2
            sAMAccountName=user3
                memberOf=CN=ROLE_USER,OU=OPENKM,DC=company,DC=com
                userPrincipalName=user3@mail.com
                cn=User Name 3
            sAMAccountName=user4
                memberOf=CN=ROLE_YYYY,OU=OPENKM,DC=company,DC=com
                userPrincipalName=user4@mail.com
                cn=User Name 4

Valid groups:

  • cn=ROLE_ADMIN,ou=OPENKM,dc=company,dc=com
  • cn=ROLE_USER,ou=OPENKM,dc=company,dc=com
  • cn=ROLE_XXXX,ou=OPENKM,dc=company,dc=com
  • cn=ROLE_YYYY,ou=OPENKM,dc=company,dc=com

Valid users:

  • cn=user1,ou=organization1,dc=company,dc=com
  • cn=user2,ou=organization1,dc=company,dc=com

Invalid users:

  • cn=user3,ou=organization2,dc=company,dc=com
  • cn=user4,ou=organization2,dc=company,dc=com

Any distinguished name includes by default dc=company,dc=com except users who are not a member of ROLE_ADMIN or ROLE_USER

Configuration parameters

  • User members of ROLE_ADMIN or ROLE_USER can be created in any active directory node, because it has defined DC=company,DC=com as base filter, principal.ldap.user.search.base=DC=company,DC=com and user search filter as principal.ldap.user.search.filter=(&(objectclass=user)(|(memberOf=CN=ROLE_ADMIN,OU=OpenKM,DC=company,DC=com).
  • Groups can be created in any active directory node, because is has DC=company,DC=com as base filter, principal.ldap.role.search.base=DC=company,DC=com.
  • All Active Directory groups will be listed because it has not applied any filter restriction principal.ldap.role.search.filter=(objectclass=group).
  • Mail attribute used in this case is userPrincipalName ( the most common LDAP attribute to get mail is mail ) principal.ldap.mail.attribute=userPrincipalName.

Go to Administration > Configuration parameters:

Field / PropertyTypeDescription
principal.adapter String

com.openkm.principal.LdapPrincipalAdapter

system.login.lowercase String

true

principal.ldap.server String

ldap://192.168.xxx.xxx:389

principal.ldap.security.principal String

CN=Administrator,OU=OPENKM,DC=company,DC=com

principal.ldap.security.credentials String

password

principal.ldap.referral String

follow

principal.ldap.users.from.roles    Boolean

false

principal.ldap.user.attribute String

sAMAccountName

principal.ldap.user.search.base

List

DC=company,DC=com

principal.ldap.user.search.filter

String

(&(objectclass=user)(|(memberOf=CN=ROLE_ADMIN,OU=OpenKM,DC=company,DC=com)(memberOf=CN=ROLE_USER,OU=OpenKM,DC=company,DC=com)))

principal.ldap.username.attribute

String

cn

principal.ldap.username.search.base

String

DC=company,DC=com

principal.ldap.username.search.filter

String

(&(objectClass=person)(sAMAccountName={0}))

principal.ldap.mail.attribute String

userPrincipalName

principal.ldap.mail.search.base String

DC=company,DC=com

principal.ldap.mail.search.filter String

(&(objectClass=person)(sAMAccountName={0}))

principal.ldap.role.attribute

String

cn

principal.ldap.role.search.base

List

DC=company,DC=com

principal.ldap.role.search.filter

String

(objectclass=group)

principal.ldap.roles.by.user.attribute

String

memberOf

principal.ldap.roles.by.user.search.base

String

DC=company,DC=com

principal.ldap.roles.by.user.search.filter

String

(&(objectClass=person)(sAMAccountName={0}))

principal.ldap.users.by.role.attribute

String

member

principal.ldap.users.by.role.search.base

String

OU=OpenKM,DC=company,DC=com

principal.ldap.users.by.role.search.filter

String

(&(objectClass=group)(cn={0}))

OpenKM.xml

  • Users created in any Active Directory node members of ROLE_ADMIN or ROLE_USER will be able to log in because it has defined DC=company,DC=com as the base filter, and as user account filter.
  • Groups read by OpenKM can be created in an Active Directory node, because it has defined DC=company,DC=com as the base filter.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:security="http://www.springframework.org/schema/security"
             xmlns:task="http://www.springframework.org/schema/task"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/security
                                 http://www.springframework.org/schema/security/spring-security.xsd
                                 http://www.springframework.org/schema/task
                                 http://www.springframework.org/schema/task/spring-task.xsd">
 
<security:authentication-manager alias="authenticationManager">
     <security:authentication-provider ref="ldapAuthProvider" />
  </security:authentication-manager>
 
<beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
  <beans:constructor-arg value="ldap://192.168.xxx.xxx"/>
  <beans:property name="userDn" value="CN=connect,OU=OpenKM,DC=company,DC=com"/>
  <beans:property name="password" value="****"/>
  <beans:property name="baseEnvironmentProperties">
     <beans:map>
        <beans:entry>
          <beans:key>
            <beans:value>java.naming.referral</beans:value>
          </beans:key>
          <beans:value>follow</beans:value>
        </beans:entry>
      </beans:map>
   </beans:property>
</beans:bean>
 
<beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
  <beans:constructor-arg>
    <beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
      <beans:constructor-arg ref="contextSource"/>
      <beans:property name="userSearch" ref="userSearch"/>
    </beans:bean>
  </beans:constructor-arg>
  <beans:constructor-arg>
    <beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
      <beans:constructor-arg ref="contextSource"/>
      <beans:constructor-arg value="DC=company,DC=com"/>
      <beans:property name="groupSearchFilter" value="member={0}"/>
      <beans:property name="groupRoleAttribute" value="cn"/>
      <beans:property name="searchSubtree" value="true" />
      <beans:property name="convertToUpperCase" value="false" />
      <beans:property name="rolePrefix" value="" />
    </beans:bean>
  </beans:constructor-arg>
</beans:bean>
 
<beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
  <beans:constructor-arg index="0" value="DC=company,DC=com" />
  <beans:constructor-arg index="1" value="(&amp;(sAMAccountName={0})(|(memberOf=CN=ROLE_ADMIN,OU=OpenKM,DC=company,DC=com)(memberOf=CN=ROLE_USER,OU=OpenKM,DC=company,DC=com)))" />
  <beans:constructor-arg index="2" ref="contextSource" />
  <beans:property name="searchSubtree" value="true" />
</beans:bean>
 
</beans:beans>