LDAP troubleshooting
How to do a nested group membership filter in active directly
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
If you see an exception like this "org.springframework.context.ApplicationContextException: No UserDetailsService registered," you might add in your openkm.xml this line:
<beans:bean id="userDetailService" class="com.openkm.spring.UserTenantDetailsService"/>
This issue only affects versions of OpenKM where the "remember me" feature was included. Take a look at the Changelog to check if your OpenKM is affected.
You can find more information about the "remember me" configuration in the Security configuration parameters.
javax.naming.PartialResultException error
If you see an exception like this "javax.naming.PartialResultException" you probably can not use Active Directory basic configuration.
javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'cn=users,dc=company,dc=com'
Solution 1:
Use ports 3268 or 3269 ( ldaps ) in the AD connection.
Go to Administration > Configuration parameters:
Field / Property | Type | Description |
---|---|---|
principal.ldap.server | String |
ldap://192.168.xxx.xxx:3268 |
Information about ports 3268 and 3269 at :
Solution 2:
Enable ldap to ignore the partial results exception property.
Go to Administration > Configuration parameters:
Field / Property | Type | Description |
---|---|---|
ldap.ignore.partial.result.exception | Boolean |
true |
Solution 3:
Enable 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
If your LDAP server is configured under SSL, then you should use ldaps://
Solution:
Go to Administration > Configuration parameters:
Change server connection URL to ldaps.
Field / Property | Type | Description |
---|---|---|
principal.ldap.server | String |
ldaps://192.168.0.6:389 |
Slow login or not able to login
It may be a problem with LDAP DNS names resolution.
Solution:
To prevent this issue - especially on Windows OS Family - it's a good practice to add all subdomains in the application server's host file ( /etc/hosts for Linux or C:/Windows/system32/driver/etc/host for windows ).
Example based with active directory ( LDAP ) with distinguished base name dc=company,dc=com, and server at SBSSERVER domain server name.
10.10.1.2 company.com
10.10.1.2 SBSSERVER SBSSERVER.company.com
10.10.1.2 Schema.Configuration.company.com
10.10.1.2 Configuration.company.com
10.10.1.2 DomainDnsZones.company.com
10.10.1.2 ForestDnsZones.company.com
More information is at the OpenKM forum.
If, after adding these subdomains, the login continues taking a lot of time, check with your IT Security team if they have enabled some micro-segmentation policies. That may be another reason why login takes so much time.
To check connections done by the application in the login process to the AD, can execute the following command line:
$ tcpdump -A tcp port 389
To capture only the request:
$ sudo tcpdump -i any port 389 > login-test-request.txt
Wireshark dump (pcap) and transform to human readable:
$ sudo tcpdump -A port 389 -w login-test.pcap
$ tshark -r login-test.pcap -V > login-test.txt
Force all users to be members of ROLE_USER.
In vast user AD repositories, it can not be practiced for the AD administrator to add a new group to all the users; in this case, we can force across xml login configuration that any logged user be a member of ROLE_USER. Must be added 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
If you see an error like this "org.springframework.beans.factory.parsing.BeanDefinitionParsingException" you probably have some wrong spring version set in the openkm.xml:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema with Spring Security 3.2. Please update your schema declarations to the 3.2 schemas.
Offending resource: URL [file:/home/openkm/tomcat-8.5.69/openkm.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.fatal(FailFastProblemReporter.java:59)
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
The transport encryption required error usually happens when you are trying to connect with ldaps ( with SSL encryption ), and you have not configured the trust certificate into the JAVA certs storage.
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, for it follows the steps below:
$ openssl s_client -showcerts -connect your.ldap.server.com:636
The OpenSSL windows binaries https://wiki.openssl.org/index.php/Binaries ( version tested https://indy.fulgan.com/SSL/ )
The output will contain several entries delimited with the following:
-----BEGIN CERTIFICATE-----
aklfhskfadljasdl1340234234ASDSDFSDFSDFSDFSD
....
-----END CERTIFICATE-----
To prevent the loss of JKS after the Java upgrade, do not create the JKS under the JDK folders.
In the sample below, it is supposed the $TOMCAT_HOME is set to /home/openkm/tomcat
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.crt
Finally enable trust store into the file $TOMCAT_HOME/bin/setenv.sh
# JAVA enable trust store
JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=/home/openkm/tomcat/jks/cacerts -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
Additional information:
Ldap error: Caused by java.security.cert.CertificateException: No subject alternative DNS name matching
In the log, maybe show 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 more
Or 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