LDAP troubleshooting
How to do a nested group membership filter in Active Directory
Section titled “How to do a nested group membership filter in Active Directory”The sample below demonstrates how to configure AD search to retrieve users that are members of some role that is a member of ROLE_OPENKM.
| Field / Property | Type | Description |
|---|---|---|
| principal.ldap.user.search.filter | String | ((objectclass=user)((memberOf:1.2.840.113556.1.4.1941:=CN=ROLE_OPENKM,OU=OpenKM,DC=company,DC=com)) |
No UserDetailsService registered error
Section titled “No UserDetailsService registered error”If you see an exception like this “org.springframework.context.ApplicationContextException: No UserDetailsService registered,” you might add this line to your openkm.xml:
<beans:bean id="userDetailService" class="com.openkm.spring.UserTenantDetailsService"/>javax.naming.PartialResultException error
Section titled “javax.naming.PartialResultException error”If you see an exception like this “javax.naming.PartialResultException” you probably cannot use Active Directory basic configuration.
Solution 1:
Use ports 3268 or 3269 (LDAPS) for the AD connection.
Go to Administration > Configuration parameters:
| Field / Property | Type | Description |
|---|---|---|
| principal.ldap.server | String | ldap://192.168.xxx.xxx:3268 |
Solution 2:
Enable LDAP to ignore the partial result exception property.
Go to Administration > Configuration parameters:
| Field / Property | Type | Description |
|---|---|---|
| ldap.ignore.partial.result.exception | Boolean | true |
Solution 3:
Enable the LDAP referral property.
Go to Administration > Configuration parameters:
| Field / Property | Type | Description |
|---|---|---|
| principal.ldap.referral | String | follow |
Read these articles:
Can’t connect to LDAP server
Section titled “Can’t connect to LDAP server”If your LDAP server is configured under SSL, then you should use ldaps://.
Solution:
Go to Administration > Configuration parameters:
Change the server connection URL to ldaps://.
| Field / Property | Type | Description |
|---|---|---|
| principal.ldap.server | String | ldaps://192.168.0.6:389 |
Slow login or unable to log in
Section titled “Slow login or unable to log in”It may be a problem with LDAP DNS name resolution.
Solution:
To prevent this issue - especially on Windows OS family - it is good practice to add all subdomains to the application server’s hosts file (/etc/hosts for Linux or C:\Windows\System32\drivers\etc\hosts for Windows).
Example based on Active Directory (LDAP) with distinguished base name dc=company,dc=com and server domain name SBSSERVER.
10.10.1.2 company.com10.10.1.2 SBSSERVER SBSSERVER.company.com10.10.1.2 Schema.Configuration.company.com10.10.1.2 Configuration.company.com10.10.1.2 DomainDnsZones.company.com10.10.1.2 ForestDnsZones.company.comMore information is available at the OpenKM forum.
Force all users to be members of ROLE_USER.
Section titled “Force all users to be members of ROLE_USER.”In large AD user repositories, it is not feasible for the AD administrator to add a new group to all users; in this case, we can enforce via the XML login configuration that any logged-in user be a member of ROLE_USER. Add the XML tag <beans:property name=“defaultRole” value=“ROLE_USER” />.
For example:
<?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:property name="defaultRole" value="ROLE_USER" /> </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>org.springframework.beans.factory.parsing.BeanDefinitionParsingException
Section titled “org.springframework.beans.factory.parsing.BeanDefinitionParsingException”If you see an error like this “org.springframework.beans.factory.parsing.BeanDefinitionParsingException” you probably have an incorrect Spring version set in the openkm.xml:
Solution:
Edit the openkm.xml file and remove the version numbers:
<?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-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">to
<?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">LDAP: error code 8 - BindSimple: Transport encryption required
Section titled “LDAP: error code 8 - BindSimple: Transport encryption required”The “transport encryption required” error usually occurs when you try to connect with LDAPS (SSL encryption) and have not configured the trust certificate in the Java truststore.
First, check that you are using “ldaps://” (ends with ‘s’) in your openkm.xml file for the connection; when you get this error, use it.
The first step is to get the certificate from the server; to do so, follow the steps below:
$ openssl s_client -showcerts -connect your.ldap.server.com:636The output will contain several entries delimited with the following:
-----BEGIN CERTIFICATE-----aklfhskfadljasdl1340234234ASDSDFSDFSDFSDFSD....-----END CERTIFICATE-----Copy the last certificate entry into a file (ldapca.crt).
Then, add it to the Java keystore in $JRE_HOME/lib/security.
$ cd $TOMCAT_HOME$ mkdir jks$ keytool -import -alias ldapca_self_sign -keystore cacerts -storepass changeit -file ldapca.crtFinally, enable the trust store in the file $TOMCAT_HOME/bin/setenv.sh
# JAVA enable trust storeJAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=/home/openkm/tomcat/jks/cacerts -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"LDAP error: Caused by java.security.cert.CertificateException: No subject alternative DNS name matching
Section titled “LDAP error: Caused by java.security.cert.CertificateException: No subject alternative DNS name matching”In the log, you may see some stack trace errors like:
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching ldap.openkm.com found. at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214) at sun.security.util.HostnameChecker.match(HostnameChecker.java:96) at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:459) at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621) ... 72 moreOr like:
Caused by: org.springframework.ldap.CommunicationException: simple bind failed: ldap.openkm.com:636; nested exception is javax.naming.CommunicationException: simple bind failed: email.ied.edu.hk:636 [Root exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching email.ied.edu.hk found.] at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:100) at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:285) at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:119) at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:138) at org.springframework.ldap.core.LdapTemplate.executeReadOnly(LdapTemplate.java:791) at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntry(SpringSecurityLdapTemplate.java:194) at org.springframework.security.ldap.search.FilterBasedLdapUserSearch.searchForUser(FilterBasedLdapUserSearch.java:116) at org.springframework.security.ldap.authentication.BindAuthenticator.authenticate(BindAuthenticator.java:90) at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:178)Modify JVM configuration parameters in setenv.sh or setenv.bat by adding the JVM configuration parameter:
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true