Realm Configuration HOW-TO

Table of Contents

Quick Start

This document describes how to configure Tomcat to support container managed security, by connecting to an existing "database" of usernames, passwords, and user roles. You only need to care about this if you are using a web application that includes one or more <security-constraint> elements, and a <login-config> element defining how users are required to authenticate themselves. If you are not utilizing these features, you can safely skip this document.

For fundamental background information about container managed security, see the Servlet Specification (Version 2.4), Section 12.

For information about utilizing the Single Sign On feature of Tomcat (allowing a user to authenticate themselves once across the entire set of web applications associated with a virtual host), see here.

Overview

What is a Realm?

A Realm is a "database" of usernames and passwords that identify valid users of a web application (or set of web applications), plus an enumeration of the list of roles associated with each valid user. You can think of roles as similar to groups in Unix-like operating systems, because access to specific web application resources is granted to all users possessing a particular role (rather than enumerating the list of associated usernames). A particular user can have any number of roles associated with their username.

Although the Servlet Specification describes a portable mechanism for applications to declare their security requirements (in the web.xml deployment descriptor), there is no portable API defining the interface between a servlet container and the associated user and role information. In many cases, however, it is desirable to "connect" a servlet container to some existing authentication database or mechanism that already exists in the production environment. Therefore, Tomcat defines a Java interface (org.apache.catalina.Realm) that can be implemented by "plug in" components to establish this connection. Six standard plug-ins are provided, supporting connections to various sources of authentication information:

  • JDBCRealm - Accesses authentication information stored in a relational database, accessed via a JDBC driver.
  • DataSourceRealm - Accesses authentication information stored in a relational database, accessed via a named JNDI JDBC DataSource.
  • JNDIRealm - Accesses authentication information stored in an LDAP based directory server, accessed via a JNDI provider.
  • UserDatabaseRealm - Accesses authentication information stored in an UserDatabase JNDI resource, which is typically backed by an XML document (conf/tomcat-users.xml).
  • MemoryRealm - Accesses authentication information stored in an in-memory object collection, which is initialized from an XML document (conf/tomcat-users.xml).
  • JAASRealm - Accesses authentication information through the Java Authentication & Authorization Service (JAAS) framework.

It is also possible to write your own Realm implementation, and integrate it with Tomcat. To do so, you need to:

  • Implement org.apache.catalina.Realm,
  • Place your compiled realm in $CATALINA_HOME/lib,
  • Declare your realm as described in the "Configuring a Realm" section below,
  • Declare your realm to the MBeans Descriptors.

Configuring a Realm

Before getting into the details of the standard Realm implementations, it is important to understand, in general terms, how a Realm is configured. In general, you will be adding an XML element to your conf/server.xml configuration file, that looks something like this:

<Realm className="... class name for this implementation"
       ... other attributes for this implementation .../>

The <Realm> element can be nested inside any one of of the following Container elements. The location of the Realm element has a direct impact on the "scope" of that Realm (i.e. which web applications will share the same authentication information):

  • Inside an <Engine> element - This Realm will be shared across ALL web applications on ALL virtual hosts, UNLESS it is overridden by a Realm element nested inside a subordinate <Host> or <Context> element.
  • Inside a <Host> element - This Realm will be shared across ALL web applications for THIS virtual host, UNLESS it is overridden by a Realm element nested inside a subordinate <Context> element.
  • Inside a <Context> element - This Realm will be used ONLY for THIS web application.

Common Features

Digested Passwords

For each of the standard Realm implementations, the user's password (by default) is stored in clear text. In many environments, this is undesirable because casual observers of the authentication data can collect enough information to log on successfully, and impersonate other users. To avoid this problem, the standard implementations support the concept of digesting user passwords. This allows the stored version of the passwords to be encoded (in a form that is not easily reversible), but that the Realm implementation can still utilize for authentication.

When a standard realm authenticates by retrieving the stored password and comparing it with the value presented by the user, you can select digested passwords by placing a CredentialHandler element inside your <Realm> element. An easy choice to support one of the algorithms SSHA, SHA or MD5 would be the usage of the MessageDigestCredentialHandler. This element must be configured to one of the digest algorithms supported by the java.security.MessageDigest class (SSHA, SHA or MD5). When you select this option, the contents of the password that is stored in the Realm must be the cleartext version of the password, as digested by the specified algorithm.

When the authenticate() method of the Realm is called, the (cleartext) password specified by the user is itself digested by the same algorithm, and the result is compared with the value returned by the Realm. An equal match implies that the cleartext version of the original password is the same as the one presented by the user, so that this user should be authorized.

To calculate the digested value of a cleartext password, two convenience techniques are supported:

  • If you are writing an application that needs to calculate digested passwords dynamically, call the static Digest() method of the org.apache.catalina.realm.RealmBase class, passing the cleartext password, the digest algorithm name and the encoding as arguments. This method will return the digested password.
  • If you want to execute a command line utility to calculate the digested password, simply execute
    CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} {cleartext-password}
    and the digested version of this cleartext password will be returned to standard output.

If using digested passwords with DIGEST authentication, the cleartext used to generate the digest is different and the digest must use one iteration of the MD5 algorithm with no salt. In the examples above {cleartext-password} must be replaced with {username}:{realm}:{cleartext-password}. For example, in a development environment this might take the form testUser:Authentication required:testPassword. The value for {realm} is taken from the <realm-name> element of the web application's <login-config>. If not specified in web.xml, the default value of Authentication required is used.

Usernames and/or passwords using encodings other than the platform default are supported using

CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} -e {encoding} {input}

but care is required to ensure that the input is correctly passed to the digester. The digester returns {input}:{digest}. If the input appears corrupted in the return, the digest will be invalid.

The output format of the digest is {salt}${iterations}${digest}. If the salt length is zero and the iteration count is one, the output is simplified to {digest}.

The full syntax of CATALINA_HOME/bin/digest.[bat|sh] is:

CATALINA_HOME/bin/digest.[bat|sh] [-a <algorithm>] [-e <encoding>]
        [-i <iterations>] [-s <salt-length>] [-k <key-length>]
        [-h <handler-class-name>] <credentials>
  • -a - The algorithm to use to generate the stored credential. If not specified, the default for the handler will be used. If neither handler nor algorithm is specified then a default of SHA-512 will be used
  • -e - The encoding to use for any byte to/from character conversion that may be necessary. If not specified, the system encoding (Charset#defaultCharset()) will be used.
  • -i - The number of iterations to use when generating the stored credential. If not specified, the default for the CredentialHandler will be used.
  • -s - The length (in bytes) of salt to generate and store as part of the credential. If not specified, the default for the CredentialHandler will be used.
  • -k - The length (in bits) of the key(s), if any, created while generating the credential. If not specified, the default for the CredentialHandler will be used.
  • -h - The fully qualified class name of the CredentialHandler to use. If not specified, the built-in handlers will be tested in turn (MessageDigestCredentialHandler then SecretKeyCredentialHandler) and the first one to accept the specified algorithm will be used.

Example Application

The example application shipped with Tomcat includes an area that is protected by a security constraint, utilizing form-based login. To access it, point your browser at http://localhost:8080/examples/jsp/security/protected/ and log on with one of the usernames and passwords described for the default UserDatabaseRealm.

Manager Application

If you wish to use the Manager Application to deploy and undeploy applications in a running Tomcat installation, you MUST add the "manager-gui" role to at least one username in your selected Realm implementation. This is because the manager web application itself uses a security constraint that requires role "manager-gui" to access ANY request URI within the HTML interface of that application.

For security reasons, no username in the default Realm (i.e. using conf/tomcat-users.xml is assigned the "manager-gui" role. Therefore, no one will be able to utilize the features of this application until the Tomcat administrator specifically assigns this role to one or more users.

Realm Logging

Debugging and exception messages logged by a Realm will be recorded by the logging configuration associated with the container for the realm: its surrounding Context, Host, or Engine.

Standard Realm Implementations

JDBCRealm

Introduction

JDBCRealm is an implementation of the Tomcat Realm interface that looks up users in a relational database accessed via a JDBC driver. There is substantial configuration flexibility that lets you adapt to existing table and column names, as long as your database structure conforms to the following requirements:

  • There must be a table, referenced below as the users table, that contains one row for every valid user that this Realm should recognize.
  • The users table must contain at least two columns (it may contain more if your existing applications required it):
    • Username to be recognized by Tomcat when the user logs in.
    • Password to be recognized by Tomcat when the user logs in. This value may in cleartext or digested - see below for more information.
  • There must be a table, referenced below as the user roles table, that contains one row for every valid role that is assigned to a particular user. It is legal for a user to have zero, one, or more than one valid role.
  • The user roles table must contain at least two columns (it may contain more if your existing applications required it):
    • Username to be recognized by Tomcat (same value as is specified in the users table).
    • Role name of a valid role associated with this user.
Quick Start

To set up Tomcat to use JDBCRealm, you will need to follow these steps:

  1. If you have not yet done so, create tables and columns in your database that conform to the requirements described above.
  2. Configure a database username and password for use by Tomcat, that has at least read only access to the tables described above. (Tomcat will never attempt to write to these tables.)
  3. Place a copy of the JDBC driver you will be using inside the $CATALINA_HOME/lib directory. Note that only JAR files are recognized!
  4. Set up a <Realm> element, as described below, in your $CATALINA_BASE/conf/server.xml file.
  5. Restart Tomcat if it is already running.
Realm Element Attributes

To configure JDBCRealm, you will create a <Realm> element and nest it in your $CATALINA_BASE/conf/server.xml file, as described above. The attributes for the JDBCRealm are defined in the Realm configuration documentation.

Example

An exa