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:

  • The realm can either use a pattern to determine the distinguished name (DN) of the user's directory entry, or search the directory to locate that entry.
  • The realm can authenticate the user either by binding to the directory with the DN of the user's entry and the password presented by the user, or by retrieving the password from the user's entry and performing a comparison locally.
  • Roles may be represented in the directory as explicit entries found by a directory search (e.g. group entries of which the user is a member), as the values of an attribute in the user's entry, or both.

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:


Real Life Implementations.#

Disclaimers#

This is a very simple Example and does not address many items of the implementation. Contact Directory Engineering for more details.

Now adding some praticalities to this discussion for "real life" implementations.

First let us look at the variety of approaches to using LDAP for authentication.

Pattern Distinguished Name (DN)#

"The realm can either use a pattern to determine the distinguished name (DN) of the user's directory entry, or search the directory to locate that entry."

Authenticate or Performing a Comparison#

"The realm can authenticate the user either by binding to the directory with the DN of the user's entry and the password presented by the user, or by retrieving the password from the user's entry and performing a comparison locally. "

Never perform a Password Comparrison. Comparing the LDAP entries password typically bypasses the LDAP server's built-in controls for such items as:

  • Password Expired
  • Account Disabled
  • Intruder Detection
  • Any other rules that are applied by binding to the server.

Group Entries or Values of an Attribute#

Groups are Bad and it is a Best practice to avoid groups in all but the smallest LDAP directories. It is recommended to use Container Authentication and Authorization Using User Attribute Values for Tomcat Role

The Bottom Line(s)#

  • Always bind
  • Use Role Attribute Values on the User Entry

How To Use JNDI#

You will typically need to modify two files to setup Tomcat to use JNDI with LDAP. The server.xml file will define the Security Realms and the applications web.xml file will define the "Security Constraints".

Security Realms#

A security realm is a mechanism used for protecting Web application resources. It gives you the ability to protect a resource with a defined security constraint and then define the user roles that can access the protected resource. Tomcat has this type of realm functionality built in.

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"
                /> 
NOTE: The realm configuration is using LDAPS (SSL) to contact the LDAP server and requires that the certificate be imported to the JVM keystore that tomcat is using. We have not found a method to allow the LDAPS connection to be made when NOT using the integrate cacerts keystore of the JVM. If someone know how, please advise.

Another example and some more detailed LDAP information is provided here: Using User Attribute Values for Tomcat Roles

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.

Attribute Definitions#

These are the XML Attributes of the XML Element Realm and what the values represent:
  • className - The fully qualified Java class name of this Realm implementation. You MUST specify the value "org.apache.catalina.realm.JNDIRealm" here.
  • connectionURL - The connection URL to be passed to the JNDI driver when establishing a connection to the directory.
  • userBase - The base element for user searches performed using the userSearch expression. If not specified, the top level element in the directory context will be used. Not used if you are using the userPattern expression.
  • userSearch - The LDAP filter expression to use when searching for a user's directory entry, with {0} marking where the actual username should be inserted. Use this property (along with the userBase and userSubtree properties) instead of userPattern to search the directory for the user's entry.
  • userRoleName - The name of an attribute in the user's directory entry containing zero or more values for the names of roles assigned to this user
  • userSubtree - Set to true if you want to search the entire subtree of the element specified by the userBase property for the user's entry. The default value of false causes only the top level to be searched. Not used if you are using the userPattern expression.

Security Constraints#

To "protect" an Tomcat Application, then you will need to modify the web.xml file for the application. Typically, it is found $CATALINA_HOME/webapps/DirectoryWiki/WEB-INF
<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>

What This Means#

Typically, the user will provide their "uid" and password on a form provided by the developer. The Realm will search for the User Entry and return the Fully Distinguished Name (FDN).

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 alowed 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.

Things To Watch#

Make It Secure#

First, all LDAP and HTTP authentication should be done via SSL connetcions. As values passed (Like passwords) over "simple" LDAP binds or HTTP are in clear text and therefore couls expose password values. Refer to Tomcat And SSL for information on http for Tomcat.
  • Always use SSL to bind to the LDAP directory.
  • Always HTTP FORM Authentication over SSL.

LDAP Trace#

When we look at the setup from a trace, we see the searchRequest by the tomcatadmin account from tomcat Server (192.168.0.15) and then a bind of the user (jim): (We did this over cleartext)
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

More Information#

There might be more information for this subject on one of the following:

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-15) was last changed on 2013-08-27 18:22 by jim