posts - 23,comments - 12,trackbacks - 0

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.

16 Responses to “How To Authenticate a Servlet App with Windows Passwords”

  1. carmen Says:

    hi,
    I cannot get tagish working! I don’t know what I’m doing wrong. Someone can help me please? I’ve followed the list above step by step :(
    System: Struts and tomcat on W2000 professional (but also tried same config on W2000 server and it doesn’t work either)
    Thanks

    stack trace:

    19-Jul-2004 17:17:12 org.apache.catalina.realm.JAASRealm authenticate
    WARNING: Login exception authenticating username Administrator
    javax.security.auth.login.LoginException: Error: javax.security.auth.callback.TextInputCallback@da3772 not available to garner authentication information from the user
    at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:675)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:129)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:610)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java:607)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:534)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:281)
    at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:129)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:793)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:702)
    at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:571)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:644)
    at java.lang.Thread.run(Thread.java:534)
    19-Jul-2004 17:20:17 org.apache.coyote.http11.Http11Protocol pause
    INFO: Pausing Coyote HTTP/1.1 on http-8080

  2. Chris Maeda Says:

    I saw this problem; it was caused by a mistake in the config files. Does Tomcat throw an earlier exception that complains about parsing the tagish login config file? If the parse fails, the callback handler will not be initialized.

  3. Manju Panjwani Says:

    I am also facing the same issue.
    WARNING: Login exception authenticating username Administrator
    javax.security.auth.login.LoginException: Error: javax.security.auth.callback.TextInputCallback@da3772 not available to garner authentication information from the user
    at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    Were you able to resolve the above? Please guide.

  4. Louis A Johannson Says:

    I’ve got the Tagish example working fine where I can use the batch login.bat to test a

    login/authentication. I can also integrate it with JAAS security and have it authenticate me

    against my network in a console application. However, as soon as I try to tie it into

    Tomcat, I get stuck. (I’m trying an web-app example based on BASIC authentication)

    I think my files are in the correct places (I get different errors when they’re missing) and

    I can make my tomcat example web-app work using a different authentication method (the

    tomcat manager’s memory-realm user authentication works fine) and I’ve even done the JAAS

    example to replace the security realm of the tomcat manager app with JAAS.

    The problem I’m getting now is that I get a serious bomb that kills tomcat as soon as I try

    to access the protected directory:

    An unexpected exception has been detected in native code outside the VM.
    Unexpected Signal : EXCEPTION_ACCESS_VIOLATION (0xc0000005) occurred at PC=0x7BF6256
    Function=[Unknown.]
    Library=C:\Projects\workspace3\example.Tomcat_NT\lib\NTSystem.dll

    NOTE: We are unable to locate the function name symbol for the error
    just occurred. Please refer to release documentation for possible
    reason and solutions.

    Current Java thread:
    at com.tagish.auth.win32.NTSystem.logon(Native Method)
    - locked <0x10024d98> (a com.tagish.auth.win32.NTSystem)
    at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:134)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...

    I’m really rather at a loss as to why this is happening. It ‘feels’ like there is something

    wrong with the tagish module, but if others got it working I really don’t know. Did you have

    to extend it at all? Or wrap it up in an implemented JAAS interface? (but tagish has done

    that already haven’t they?)

    Config:
    Tomcat 5.0.27/28
    Eclipse 3.0
    Sysdeo eclipse/tomcat plugin
    J2SDK 1.4.2_05
    Tagish 1.0.3

    I also tried plugging the tagish module straight into a clean tomcat (without using any of

    my code) to replace the security realm of the manager web-app. The error is slightly

    different here:

    7-Sep-2004 12:46:17 AM org.apache.catalina.realm.JAASRealm authenticate
    WARNING: Login exception authenticating username louis
    javax.security.auth.login.LoginException: Error: javax.security.auth.callback.Te
    xtInputCallback@354749 not available to garner authentication information from t
    he user
    at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:675)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:1
    29)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:610)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java
    :607)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:534)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:316)
    at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(Bas
    icAuthenticator.java:129)

    Does anyone have a clean working example in tomcat they’d be willing to zipup and post?

    My proper email prefix is: louis_a_j
    Suffix: telus.net

  5. Louis A. Johannson Says:

    P.S. As per the following post:
    Tagish and JBOSS
    I’ve tried substituting a default domain into the tagish.login (my workgroup) but that just brought me back to the previous exception which kills tomcat.
    Note: I’ve tried this on both an NT4 domain and on a windows 2000 workgroup with the same results in both.

  6. Louis Johannson Says:

    Sorry, the link I included broke:
    http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3837312#3837312

  7. Aaron Hawkins Says:

    I have the same problem as the #4 comment on this page submited by Louis Johannson. I can authenticate using a console app, but when I try and follow the instructions to authenticate agains Tomcat, my jvm blows up with the same error. It seems that there is a problem with NTSystem.dll. If it is anywhere on my path, my jvm will blow up when I try and use tomcat. If I delete it, then I get errors about it not being found. Has anyone found a solution to this? Any help would be appreciated.

  8. Aaron Hawkins Says:

    I have found the solution to the problem described by post #4. The NTSystem.dll doesn’t appear to like a null username. When trying to get this to work with Tomcat, if you use Form based authentication, you can avoid sending a null username, and everything works great.

  9. rafal piotrowski Says:

    Hi
    I try to use samba ntlm filter first and I’ve got some problem.
    If I try to open some web page from my web app the internet browser logon dialog always shows.
    How should I configure my Windows XP workstation to eliminate this dialog.

  10. mgr Says:

    Hi,
    I have a question about automatic authentication.

    I have a windows 2003 server with active directory. Tomcats and JAAS libraries are correctly installed and configured. When I try to access to the web site I protected by the realm, a login/password is requiered, and I can access to the web site after authentication.

    My question is: is it possible not to have the login/password dialog box if I access to Web site with a computer that belongs to the domain I create and if i’m logged with the correct login/password to have access.
    I would automatically enter to the web site as I’m already authenticated in the Windows session. Is that possible?

    The case is the same if I try locally, on the server. I’m logged with an account who belongs to the domain, and this account belongs to the group I defined in the active directory and in the web.xml file of the web site. But the system ask me the login/password and don’t acces directly to the web site.

    Thanks

  11. Mel Riffe Says:

    I’m starting down this path also and having some troubles. One thing I noticed there is a typo in the instructions. I think you should update the java.security file like so:
    login.config.url.1=file:${java.home}/jre/lib/security/tagish.login

    Plus I added the following to Tagish’s login.bat:
    -Djava.security.auth.login.config=C:\j2sdk1.4.2_06\jre\lib\security\tagish.login

    Next step…authenticating in Tomcat…

    - Mel

  12. Trinition Says:

    I modified the NTSystemLogin source in the Tagish JAAS module to throw a FailedLoginException for a null username or password,a nd not normal BASIC auth works. I presume the null was blowing up in the Tagish NTSYstem.dll or the call it makes to the Win32 API. I shared my update with the Tagish JAAS author, so I’ll see what he thinks.

  13. vicky Says:

    Hi, I am trying to use tagish with tomcat 5.0.27 and exactly getting all the same problems mentioned by others. Is there any clear way to use tagish??

    Please advice.
    thanks
    aks

  14. jh Says:

    does this also work on websphere server?

  15. Kris Dover Says:

    Aaron Hawkins, thanks a million. My tomcat 5.0.28 was also crashing with the Basic authentication and i noticed the username null entries in the stdout.log and wondered if that was causing it, but never made an attempt to resolve it using form base authentication until reading your message. seemed very unusual that tomcat’s basic authentication was returning nulls even when the correct username and password were entered on the first try. go figure. Trinition, i haven’t seen an update with your recommended fix, so i might just hack the java code myself. thanks.

  16. Joe Says:

    The TextInputCallback is issued when you do not have a defaultdomain=”yourdomain” in your tagish.login file, there is no way for a TextInputCallback to work through the servlet, the source should be changed so that it could parse the domain from the username callback if no default domain is specified, however some people may want to have a text callback for applications instead of servlets.

    The Null username does indeed crash the NTSystem.dll, simply change the login attempt:

    succeeded = false
    ntSystem.logon(username, password, domain); // may throw
    succeeded = true;

    to:

    succeeded = false;
    if (username == null || password == null) {
    throw new LoginException("Error: " + username == null ? "username" : "password" + ", null, not allowed");
    }
    ntSystem.logon(username, password, domain); // may throw
    succeeded = true;

    and recompile the tagish src to a jar file, deploying it in the Tomcat/bin directory like explained above and everything will work correctly even with Basic auth.

    This is great and all, but I don’t see how tagish is using NTLM, unless you mean it is talking to my domain to get my roles using kerberos or NTLM, it does not however provide the transparent login that jCIFS does. I looked throught the tagish source and don’t see anything in there either, did I misread your article or did I overlook something?

posted on 2005-08-17 17:28 my java 阅读(1388) 评论(0)  编辑  收藏 所属分类: java身份认证转帖

只有注册用户登录后才能发表评论。


网站导航: