How To Authenticate a Servlet App With Windows Passwords

Java Development News:

How To Authenticate a Servlet App With Windows Passwords

By Chris Maeda

16 Aug 2004 | TheServerSide.com

Current instructions for configuring Tomcat for JAAS-based Windows authentication.
This is the solution for my previous post.

Samba NTLM Authentication: (Get it here.) This package configures exactly as described. I used the example servlet (NtlmHttpAuthExample) included with the package and set up the filter as in the docs. The web.xml file is here.

Notes: I tested on my home (windows) network which does not have a domain controller; I used workgroup authentication and did not test against a PDC. So YMMV.

There are two main drawbacks of this approach:

The first is that the jcifs filter (as currently implemented) does not return group membership information. If your servlet app uses security roles and security constraints, this is a problem since you need some way of getting a user’s group memberships (so the container can map them to security roles). You could get probably around this problem by extending the jcifs library to return group information; this is more work than I planned to invest. Another approach would be to create a second filter that maps user names to group memberships, perhaps using the tomcat-users.xml file. This would be cumbersome and proprietary, but it would probably work.

The second drawback is that NTLM authentication is deprecated in the Windows world. Windows 2000 and 2003 use Kerberos authentication, and only fall back on NTLM when they have to.

For these reasons, I abandoned the Samba NTLM approach and looked at the Tagish / JAAS approach.

JAAS with Tagish SSPI JAAS provider: JAAS with the Tagish SSPI-based login module is the way to go. The Tagish login module is based on the Windows SSPI API, which provides an authentication service for distributed environments using the best available protocol; i.e. it uses Kerberos when that is available and transparently falls back on NTLM when Kerbos is not available. In addition, SSPI returns the group membership information, which is necessary for servlet apps that use security roles and security constraints.

The first step in setting this up is to configure the Tagish login module according to the instructions that come with it. In a nutshell, the steps are as follows:

  • Put NTSystem.dll somewhere on your path
  • Put tagishauth.jar on your classpath
  • Copy the tagish.login file to $JAVA_HOME/jre/lib/security
  • Add this line:
    login.config.url.1=file:${java.home}/lib/security/tagish.login
    to your java.security file (in $JAVA_HOME/jre/lib/security)

You can test the configuration using the login.bat file that comes with the Tagish package. If you are on a workgroup, you may need to edit a registry setting to get network authentication to work properly. (I had to.) See this Microsoft KB article for more information; apparently, Windows XP has a “ForceGuest” parameter that forces all network logins for a workgroup to use the guest account.

The second step is to configure Tomcat to use this login module. Here are the steps I used to configure it in Tomcat 5.0.16. Note that the first 4 steps are the same ones for setting up the Tagish login module, just tweaked a little for Tomcat.

  • Copy NTSystem.dll to the Tomcat5 bin directory
  • Copy tagishauth.jar to the Tomcat5 common/lib directory
  • Copy tagish.login to the $JAVA_HOME/jre/lib/security directory. I set the defaultDomain parameter to the name of my server since I’m on a workgroup.
  • Add this line:
    login.config.url.1=file:${java.home}/lib/security/tagish.login
    to your java.security file (in $JAVA_HOME/jre/lib/security)
  • Configure a JAAS Realm in your Tomcat server.xml file using the following element:
     <Realm className="org.apache.catalina.realm.JAASRealm” debug="10? appName="NTLogin” userClassNames="com.tagish.auth.win32.typed.NTUserPrincipal” roleClassNames="com.tagish.auth.win32.typed.NTGroupPrincipal” />
    

The most important thing to remember is that the userClassNames and roleClassNames have to be exactly the same names as the classes that the Tagish login module returns. This is necessary because the Tomcat JAASRealm class compares the classnames of the principal objects with the class names given in the realm configuration. If they do not match exactly, they are ignored.

You can test the configuration using the same NtlmHttpAuthExample servlet that we used to test Samba NTLM. You need a different web.xml that uses security roles; the one I used is here. For this to work, you have to login using an account that is a member of the TESTGROUP group.

To debug it, I had to get log4j working with Tomcat5, which is an adventure in itself. It turns out that the instructions in the Tomcat5 FAQ are incomplete; you need to add commons-logging.jar to common/lib in addition to all the other steps. If you run into trouble, getting log4j debug messages out of the org.apache.catalina.realm package should tell you what is going wrong.



About the author

Chris Maeda  
Blog: http://www.cmaeda.com/index.php?p=22

Chris Maeda is president and founder of Visitrial, which makes open-source software for managing and executing clinical trials. Prior to Visitrial, he spent time as EVP & CTO for Kana Software, a public CRM software company; as co-founder and CTO of Rubric Software, a venture-funded startup in marketing automation; as a researcher with the AOP group at Xerox PARC; and as a kernel hacker with the Mach project at CMU. He holds PhD and MS degrees in computer science from CMU and a BS degree in computer science from MIT.

Related Resources