Using the JNDI Directory Realm with Tomcat can save application developers a lot of time and frustration.
Form Apache's Site The Realm Component
The JNDI Directory Realm connects Catalina (Tomcat) to an LDAP Directory, accessed through an appropriate JNDI driver, that stores usernames, passwords, and their associated roles. Changes to the directory are immediately reflected in the information used to authenticate new logins.
The directory realm supports a variety of approaches to using LDAP for authentication:
A rich set of additional attributes lets you configure the required behavior as well as the connection to the underlying directory and the element and attribute names used to retrieve information from the directory:
Now adding some practicalities to this discussion for "real life" implementations.
First let us look at the variety of approaches to using LDAP for authentication.
Never perform a Password Comparison. Comparing the LDAP entries password typically bypasses the LDAP server's built-in controls for such items as:
Modify the $CATALINA_HOME/conf/server.xml file and configure the Realm. The modification need to be something like shown below.
<Realm className="org.apache.catalina.realm.JNDIRealm" debug="10" connectionURL="ldaps://192.168.0.8:636" alternateURL="ldap://192.168.0.7:636" userBase="ou=people,dc=willeke,dc=com" userSearch="(cn={0})" userSubtree="true" userRoleName="dictcrole" connectionName="cn=admin,ou=...,dc=willeke,dc=com" connectionPassword="removed" />The realm configuration is using LDAPS to contact the LDAP server and requires that the certificate be imported to the JVM Keystore that tomcat is using.
To use a different Truststore than the cacerts Truststore of the JVM you need to set the javax.net.ssl.trustStore path or on current Tomcat versions use:
The Directory Engineering Group can not recommend the use of non-LDAPS when performing a bind as the password is not protected on the wire.
Please do not try to use the items exactly as shown as this is only an example and as this deals with the security of an application you must be careful.
<web-app> ... <!-- START OF ACCESS RESTRICTION --> <security-constraint> <web-resource-collection> <web-resource-name>Administrative Area</web-resource-name> <url-pattern>/Delete.jsp</url-pattern> </web-resource-collection> <auth-constraint> <role-name>Admin</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> <security-constraint> <web-resource-collection> <web-resource-name>Authenticated area</web-resource-name> <url-pattern>/Edit.jsp</url-pattern> <url-pattern>/Comment.jsp</url-pattern> <url-pattern>/Login.jsp</url-pattern> <url-pattern>/NewGroup.jsp</url-pattern> <url-pattern>/Rename.jsp</url-pattern> <url-pattern>/Upload.jsp</url-pattern> <http-method>DELETE</http-method> <http-method>GET</http-method> <http-method>HEAD</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> </web-resource-collection> <web-resource-collection> <web-resource-name>Read-only Area</web-resource-name> <url-pattern>/attach</url-pattern> <http-method>DELETE</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> </web-resource-collection> <auth-constraint> <role-name>Admin</role-name> <role-name>Authenticated</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/LoginForm.jsp</form-login-page> <form-error-page>/LoginForm.jsp</form-error-page> </form-login-config> </login-config> <security-role> <description> This logical role includes all authenticated users </description> <role-name>Authenticated</role-name> </security-role> <security-role> <description> This logical role includes all administrative users </description> <role-name>Admin</role-name> </security-role> ... </web-app>
The Realm will then try to authenticate the user with the FDN, from above and compare the values of the LDAP Attribute "tomcatRole" to the Realm Constraint provided in the WEB.XML file. In the example above, the <role-name>*</role-name> implies anyone that can authenticate will be allowed regardless of the value defined in the userRoleName="roomNumber".
If the user can Authenticate and the value(s) of the tomcatRole match the Realm Constraint provided, the user is allowed access.
If the <auth-constraint> was defined as:
<auth-constraint> <role-name>jim</role-name> <role-name>molly</role-name> <role-name>scott</role-name> </auth-constraint>Then only users with the persons who could authenticate who have the uid values of B003281, E178093 or U657045 would pass the auth-constraint and be allowed to access the application.
18:10:18 7E50AB90 LDAP: (192.168.1.15:39539)(0x0009:0x60) DoBind on connection 0x15446a00 18:10:18 7E50AB90 LDAP: (192.168.1.15:39539)(0x0009:0x60) Bind name:cn=tomcatadmin,dc=willeke,dc=com, version:3, authentication:simple 18:10:18 7E50AB90 LDAP: (192.168.1.15:39539)(0x0009:0x60) Sending operation result 0:"":"" to connection 0x15446a00 18:10:18 7EEBDB90 LDAP: (192.168.1.15:39539)(0x000a:0x63) DoSearch on connection 0x15446a00 18:10:18 7EEBDB90 LDAP: (192.168.0.15:39539)(0x000a:0x63) Search request: base: "ou=people,dc=willeke,dc=com" scope:2 dereference:3 sizelimit:0 timelimit:0 attrsonly:0 filter: "(cn=jim)" attribute: "dictcrole" 18:10:18 7EEBDB90 LDAP: (192.168.0.15:39539)(0x000a:0x63) nds_back_search: Search Control OID 2.16.840.1.113730.3.4.2 18:10:18 7EEBDB90 LDAP: (192.168.0.15:39539)(0x000a:0x63) Sending search result entry "cn=jim,ou=people,dc=willeke,dc=com" to connection 0x15446a00 18:10:18 7EEBDB90 LDAP: (192.168.0.15:39539)(0x000a:0x63) Sending operation result 0:"":"" to connection 0x15446a00 18:10:18 AB3F0B90 LDAP: (192.168.0.15:39539)(0x000b:0x60) DoBind on connection 0x15446a00 18:10:18 AB3F0B90 LDAP: (192.168.0.15:39539)(0x000b:0x60) Bind name:cn=jim,ou=people,dc=willeke,dc=com, version:3, authentication:simple 18:10:18 AB3F0B90 LDAP: (192.168.0.15:39539)(0x000b:0x60) Sending operation result 0:"":"" to connection 0x15446a00