What is a Tomcat Valve?

This guide does not explain or cover Tomcat Valves nor does it describe best practice/course of action when implementing Tomcat Valves.

The purpose of this guide is to simply illustrate that the SPNEGO HTTP Servlet Filter library's API can easily be used/leveraged by custom third-party code/frameworks.

This guide does provide source code as well as step-by-step instructions on how to configure Tomcat to silently authenticate users via a Tomcat Valve that uses Kerberos/SPNEGO as the authentication mechanism.

Finally, it appears that the latest version of Tomcat (7) will use servlet filters to replace/deprecate valves:

http://people.apache.org/~markt/presentations/2009-04-01-Tomcat7Servlet3.pdf

Summary

By default, Tomcat supports such authentication mechanisms as BASIC, FORM, DIGEST, etc. Unfortunately, Tomcat does not currently support Kerberos/SPNEGO as an out-of-the-box authentication mechanism.

But fortunately, Tomcat does allow you to implement and specify your own authentication mechanism via Tomcat Valves and the Authenticators.properties file.

Tomcat also provides a framework for mapping users to roles. By default, this mapping definition is specified in Tomcat's tomcat-users.xml file. This guide does not detail how to use LDAP, JDBC, etc. as the source mapping definition instead of using the Tomcat provided xml file (but the implementation is just as simple).

Goals of this guide:

  • Compile the ExampleSpnegoAuthenticatorValve.java source code
  • Add SPNEGO to Tomcat's Authenticators.properties file
  • Modify Tomcat's tomcat-users.xml mapping file
  • Modify the web.xml file
  • Run the example and see it in action!

    Before Getting Started

    If you don't already have a working tomcat server that authenticates requests via Kerberos/SPNEGO, take a look at the installing Tomcat example. After install, ensure that authentication is working by running the hello_spnego.jsp example. It is imperative that you get this working first since we will be using the values you provided in the web.xml file, and the creation of the krb5.conf file and the login.conf file.

    This guide requires that you are able to get the HTTP Servlet Filter working first.

    Once you have confirmed that all is working as expected (via the HTTP Servlet Filter method), be sure to remove/comment-out the HTTP Servlet Filter definition and filter mapping from the web.xml file.

    Obviously authentication will now fail but now we are ready to get it working again via Tomcat Valves.

    Compiling ExampleSpnegoAuthenticatorValve.java

    Download the latest spnego.jar file (spnego-r7.jar or greater) and place it under the C:\spnego-examples directory named as spnego.jar.

    Download the ExampleSpnegoAuthenticatorValve.java code and place it under the C:\spnego-examples directory.

    Before compiling ExampleSpnegoAuthenticatorValve.java, be sure to change the hard-coded property values in the file. These values should be the same values which was used in your old web.xml file (your old web.xml file had the filter definition and mapping defined and your new web.xml does not or is commented-out).

    You will also need to add C:\spnego-examples\spnego.jar, TOMCAT_HOME/lib/servlet-api.jar , TOMCAT_HOME/lib/catalina.jar, and TOMCAT_HOME/bin/tomcat-juli.jar to your classpath before compilation.

    After compilation, you need to JAR the resulting .class file and place it under the TOMCAT_HOME/lib/ directory (you can name this jar file any name you want).

    Modifying the Authenticators.properties file

    The Authenticators.properties file is located inside TOMCAT_HOME/lib/catalina.jar under the /org/apache/catalina/startup/ directory.

    Open the file in a text editor and append the following to the list of authenticators:

    SPNEGO=ExampleSpnegoAuthenticatorValve

    Modifying the tomcat-users.xml file

    By default, Tomcat stores the username/role(s) mapping in the TOMCAT_HOME/conf/tomcat-users.xml file. Consult the Tomcat docs if you prefer to use LDAP, JDBC, etc. instead of using the tomcat-users.xml file.

    This guide will use the tomcat-users.xml file for the username/role(s) mapping definition.

    Open tomcat-users.xml file in a text editor and replace it's contents with the following:

    <?xml version='1.0' encoding='utf-8'?>
    <tomcat-users>
      <role rolename="manager"/>
      <role rolename="role1"/>
      <role rolename="role2"/>
      <user username="DFelix@ATHENA.LOCAL" password="" roles="manager,role1"/>
    </tomcat-users>
    

    Notice that the value for the username attribute is fully qualified. If you want leave out the @ATHENA.LOCAL, you will have to make a small adjustment to the ExampleSpnegoAuthenticatorValve.java source code.

    Also notice that the value for the password attribute is an empty string. This value coincides with the call

    context.getRealm().authenticate(principal.getName(), "");

    in the ExampleSpnegoAuthenticatorValve.java source code (both values should be an empty string).

    Modifying the web.xml file

    Add the following to the web.xml file:

    <security-constraint>
        <web-resource-collection>
             <web-resource-name>All JSP Files</web-resource-name>
             <url-pattern>*.jsp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
             <role-name>role1</role-name>
        </auth-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>SPNEGO</auth-method>
    </login-config>
    
    <security-role>
        <role-name>role1</role-name>
    </security-role>
    

    Notice that we no longer need to define the SPNEGO HTTP Servlet Filter in the web.xml file.

    Instead, the auth-method element contains a value defined in the Authenticators.properties file, which in turn defines the Tomcat Valve named ExampleSpnegoAuthenticatorValve where by the Valve ultimately makes API calls to the SPNEGO HTTP Servlet Filter library.

    Running/Testing ExampleSpnegoAuthenticatorValve.java

    Open a browser and go to http://medusa:8080/hello_spnego.jsp

    If all is working correctly you should see the following (without being prompted):

    If you have not yet noticed, take a look again at the web.xml file. Notice that the auth-method element allows us to choose any of the authentication mechanisms (AuthN) listed in the properties file.

    Also remember that the source for the user/role mapping (AuthZ) does not have to be defined in a .xml file; you can specify JDBC, LDAP, etc. as the store for the user/role mapping.

    Essentially, Tomcat allows for an AuthN/AuthZ mechanism that is both loosely-coupled and highly-cohesive.

    Troubleshooting ExampleSpnegoAuthenticatorValve.java

    The first step to troubleshooting the Tomcat Valve is to first know with absolute certainty that authentication was working when it was configured as an HTTP Servlet Filter.

    Visit the Tomcat Valve troubleshooting page to see a list of possible solutions to some common errors.

    Links:
    pre-flight checklist
    install guide - tomcat
    install guide - jboss
    install guide - glassfish
    install guide - spring boot 2.x
    install guide - spring boot 3.x
    enable authZ with LDAP
    get user group info from LDAP
    reference docs
    api docs
    download

    Troubleshooting:
    HelloKDC.java
    hello_spnego.jsp
    HelloKeytab.java
    hello_delegate.jsp
    SpnegoHelloClient.java
    ExampleSpnegoAuthenticatorValve.java

    Examples:
    create keytab for client
    create keytab for app server
    credential delegation
    protected SOAP Web Service
    tomcat authenticator valve
    jboss authenticator valve
    authZ for standalone apps
    protecting edit button on page

    Licensing:
    GNU LGPL


    © 2009 Darwin V. Felix. All rights reserved.