Active Directory example with login based on filtering users by roles
Since version 8.1.12, the OpenLDAP integration has changed:
- The configuration parameters and login procedure remain the same.
- User data and roles are now managed in the OpenKM administration and stored in the database.
- There is a cron job called "Sync LDAP users" which synchronizes user data from LDAP to the database.
- The current configuration can be found at Active Directory mixed configuration with LDAP synced.
In this example, we'll see an Active Directory connection that allows any Active Directory-authenticated user who is a member of ROLE_USER or ROLE_ADMIN to connect.
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 dc=company,dc=com by default, except for users who are not members of ROLE_ADMIN or ROLE_USER.
The OpenKM integration with LDAP has two steps. In the first step, configure OpenKM to retrieve the list of users and roles from LDAP. This list is cached by OpenKM for 30-45 minutes to prevent overloading the LDAP server. You can clean the cache from Administration > Tools > Cache stats. In the second step, configure login. This configuration always works in real time.
Step 1 - configuration parameters
We suggest logging in to OpenKM with the admin URL (for example http://localhost:8080/openkm/admin/index) because you will need to restart the OpenKM service in the next steps and you do not want to lose administrative access.
The first action should be to modify principal.adapter parameter value and restart OpenKM service. Because the session ID is kept in the browser, you should not lose the login after the service is restarted and you can continue working in the administration. After this change, the users and roles list will be empty in the administration. Until the next parameters are successfully configured, these lists will be empty.
- Users who are members of ROLE_ADMIN or ROLE_USER can be created in any Active Directory node, because DC=company,DC=com is defined as the base filter, principal.ldap.user.search.base=DC=company,DC=com and the user search filter is 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 it has DC=company,DC=com as the base filter, principal.ldap.role.search.base=DC=company,DC=com.
- All Active Directory groups will be listed because no filter restriction has been applied: principal.ldap.role.search.filter=(objectclass=group).
- The mail attribute used in this case is userPrincipalName (the most commonly used LDAP attribute for mail is mail) principal.ldap.mail.attribute=userPrincipalName.
Go to Administration > Configuration parameters:
Field / Property | Type | Description |
---|---|---|
principal.adapter | String |
The parameter has been deprecated since version 8.1.12. com.openkm.plugin.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})) |
Step 2 - configure login
- Users created in any Active Directory node who are members of ROLE_ADMIN or ROLE_USER will be able to log in, because DC=company,DC=com is defined as the base filter, and as user account filter.
- Groups read by OpenKM can be created in any Active Directory node, because DC=company,DC=com is defined as the base filter.
Apply the changes to the openkm.properties file.
The parameter "okm.authentication.database" is used to disable database login.
The parameter "okm.authentication.ldap" is used to enable LDAP login.
#Authentication
okm.authentication.database=false
okm.authentication.ldap=true
#LDAP
ldap.server=ldap://192.168.0.13
ldap.manager.distinguished.name=CN=Administrator,CN=Users,DC=openkm,DC=local
ldap.manager.password=*secret*
ldap.base=DC=openkm,DC=local
ldap.role.attribute=cn
ldap.user.search.filter=(&(sAMAccountName={0})(|(memberOf=CN=ROLE_ADMIN,OU=OpenKM,DC=company,DC=com)(memberOf=CN=ROLE_USER,OU=OpenKM,DC=company,DC=com)))
ldap.role.search.filter=member={0}
After updating the openkm.properties file, you must restart the OpenKM service for the changes to take effect.
Another option to configure login
In some cases you might be interested in setting the configuration in the file openkm.xml; please refer to Configuring openkm.xml documentation section for more information.
<?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 name="authoritiesPopulator" ref="defaultLdapAuthoritiesPopulator"/>
</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="(&(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:bean id="defaultLdapAuthoritiesPopulator" 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>
<!--Needed for remember-me services -->
<beans:bean id="userDetailService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<beans:constructor-arg ref="userSearch"/>
<beans:constructor-arg ref="defaultLdapAuthoritiesPopulator"/>
</beans:bean>
</beans:beans>