• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Windows Authentication Using Tomcat 5.0

 
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I am using Tomcat 5.0. I need to enable Windows authentication such that when the user types the url, he should prompted for the windows login. If the windows authentication fails, he should be redirected to the web application's login page. Please help me out. I am not using IIS.

Thanks,
Visu
 
Sheriff
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Not sure what you mean by the "Windows" login.

Can you explain further?
 
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

I am guessing you want to use users to authenticate via Tomcat's HTTP auth mechanism against a MS Windows Domain user database via LDAP/ActiveDirectory.

Check out http://tomcat.apache.org/tomcat-5.0-doc/realm-howto.html and pay attention to teh JNDIRealm stuff.

I've not done this personally, but this seems the correct path to follow.

Good luck!

Stu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Thanks for the reply Thompson. My requirement is such that when a user types the url and clicks enter, the user should be allowed to enter the windows username and password. If that fails, the login page for the webapp should be displayed. I am very much confused about this. Please help me out.

Thanks in advance,
Visu
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

Hmmm...maybe your requirements are a little more complex than I understand or think reasonalbe.

That I suggest above would work like this:

1) User enters URL to your web app, www.stuisgreat.com in browser
2) Browser connects to Tomcat
3) Tomcat asks for user authentication
4) Browser prompts user for Windows user name and pwd in dialog box
5) Browser sends username and pwd to tomcat
6) Tomcat recieves user/pwd, looks at JNDI realm configuration
7) Tomcat asks the configured Windows Domain LDAP/ActiveDirectory server to authenticate user/pwd
8) Windows Domain LDAP/ActiveDirectory server responds 'user good'
9) Tomcat considers user authenticated, send requested page to browser.

Everything is good!

BUT, if the user enters a bad user/pwd then things will change:
8) Windows Domain LDAP/ActiveDirectory server responds 'user BAD'
9) Tomcat considers user not authenticated, goes back to step 3. If user fails to authenticate (give good user and password), then a HTTP 403 error page will be dispalyed. You can customize that if you like so it is pretty.

I hope this is what you are asking for.

It is not clear to me. I also hope you are not asking to authenticate agaist either the Tomcat user database or the Windows domain...that sounds tricky. If you are, well then may I suggest getting the above to work fist...that will be difficult enough.

Good luck!

Stu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Thanks for the reply Stu. Can you suggest me a starting point? I have gone through the documentation of tomcat. I was very much confused. How does the login box pop up after entering the url. I have tried it out in web.xml in security-constraints. But when i remove that and configure only the JNDIRealm in server.xml, the pop up is not being displayed and is directly redirected to the login page.

Thanks in advance,
Visu
 
Rancher
Posts: 43081
77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You need to configure both web.xml and server.xml; one without the other is not sufficient.
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

You need to have both the web app's web.xml configured correctly (security-constraint and login-config) and the server.xml's realm entry. The web.xml is what will make tomcat ask the browser for authentication. Below the security-constraint ensure you have something like this:

The 'BASIC' part is what tells tomcat to use HTTP AUTH BASIC and makes the browser give a user a popup. Nice, clean and simple.

The server.xml configuration tells tomcat how to validate the username and password.

I took a look around "the google" but did not see any clear step-by-step instructions for doing what you whant to do. Sorry.

The steps you will want to follow, or at least I would do myself is:

1) get tomcat to ask user for user password with a browser dialog box. (This ensure that your webapp is secured)

2) configure the realm and get tomcat to use the user/pwd with the realm. If you have problems here, you might want to test against the native tomcat user database (./conf/tomcat-users.xml) Like I said, I've never autheticated against a JNDI realm...so I would only do that once I knew everything else was working.

3) test that the entire application works!

Stu
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ha!!! Ulf beat me by 1 minute. :p

Also, if you have problems with this specific issue again, please show us snippets from web.xml and server.xml.

Stu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Thanks Stu. It's working fine with the Tomcat User's database.
Here's the code snippet of server.xml.

<Realm className="org.apache.catalina.realm.JNDIRealm" debug="1"
connectionURL="ldap://192.168.110.2:389" roleBase="ou=myCompany,o=Users,dc=myCompany,dc=com"
roleName="Users"
roleSearch="(Users={0})"
roleSubtree="true"/>
Please help me out.

Thanks,
Visu
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

OK, now we are back to http://tomcat.apache.org/tomcat-5.0-doc/realm-howto.html#JNDIRealm This is good. (Your are also doing something now, JNDI Realm stuff, I never done.) From this link we see...

Quick Start

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

1. Make sure your directory server is configured with a schema that matches the requirements listed above.
2. If required, configure a username and password for use by Tomcat, that has read only access to the information described above. (Tomcat will never attempt to modify this information.)
3. Place a copy of the JNDI driver you will be using (typically ldap.jar available with JNDI) inside the $CATALINA_HOME/server/lib directory (if you do not need it visible to web applications) or $CATALINA_HOME/common/lib (if it will be used both by Tomcat 5 and by your apps).
4. Set up a <Realm> element, as described below, in your $CATALINA_HOME/conf/server.xml file.
5. Restart Tomcat 5 if it is already running.



As for point 1, you will probably want to review the schema section with your domain administrator. I would not be surprised if he had to do something special, but not a big deal. (Like creating a folder on the AD structure and assigning users permissions to this folder.)

I would not worry about point 2 just yet...but review it for security reasons after everything is working.

Step 3 is obviously important. Have you a JNDI driver yet?

Step 4 is important too. Follow closely "Realm Element Attributes" with respect to your configuration. Also, I note that your configuration snippet for the JNDI real is the verbatim example. I suspect that it should reflect the realities of your Windows Domain/LDAP. Your domain administrator should be albe to help you there. (Or maybe anyone familular with how to get that information...it should be public and accessible by all users in your domain.)

OK, once you get the above done you will need to test and see what your logs report. When you get to the point where you cannot understand the logs (possibly with your domain adminstrator's help) then come back here and we can try to help more. Besure to include the realm configuration and the log file snippets.

Good luck!

Stu
[ November 08, 2006: Message edited by: Stu Thompson ]
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Thanks Stu. When I tried out using Java, it's working fine. The authentication is done. But unable to do any operation on the directory. Here's the code snippet.

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://mycompany.com");
env.put(Context.PROVIDER_URL, "ldap://mycompany.com");
env.put(Context.SECURITY_PRINCIPAL, "domainName\\visu");
env.put(Context.SECURITY_CREDENTIALS, "XXXXXXX");
DirContext ctx = new InitialDirContext(env);

When configuring in JNDI Realm, it's connecting but unable to authenticate.
Here's the code snippet of web.xml.

<security-constraint>
<display-name>Example Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<!-- Define the context-relative URL(s) to be protected -->
<url-pattern>/*</url-pattern>
<!-- If you list http methods, only those methods are protected -->
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>org.apache.catalina.realm.JNDIRealm</realm-name>
</login-config>

server.xml

<Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
connectionURL="ldap://myCompany:389/dc=domainName,dc=com"
alternateURL="ldap://myCompany:389/dc=domainName,dc=com"
userBase="ou=domainName,dc=domainName,dc=com"
userSearch="(UID={0})"
userSubtree="true"
/>

Here's the error log.

2006-11-09 12:58:08 JNDIRealm[Catalina]: Connecting to URL ldap://myCompany:389/dc=domainName,dc=com
2006-11-09 12:58:08 JNDIRealm[Catalina]: Searching for domainName\visu
2006-11-09 12:58:08 JNDIRealm[Catalina]: base: ou=domainName,dc=domainName,dc=com filter: (UID=domainName\visu
)
2006-11-09 12:58:08 JNDIRealm[Catalina]: Exception performing authentication
javax.naming.NamingException: [LDAP: error code 1 - 00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece ]; remaining name 'ou=domainName,dc=domainName,dc=com'
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3028)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2934)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2740)
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1811)
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1734)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:368)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:328)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:313)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:238)
at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1047)
at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:940)
at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:889)
at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:782)
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)

I couldn't get appropriate feedback from my admin. Where's the file located that contains the Active Directory usernames and what will be name of it. We are using Windows 2003.

Thanks in advance,
Visu
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

Ah, those admin types are always so frield and helpful, eh? (Sarcasim!) The stories I could tell you...

Anyway, when I see this snippet from your logs:

..it looks to me like Tomcat is not succesfully connecting to the domain. That means it has not even had a chance to validate the passed username and password.

I am 99.999% certain you will have to get that server.xml snippet configured correctly before proceeding.



E.g.: connectionURL should, I would think, point to your domain server. dc would be your domain name.

There is a M$ tool I used a few years ago that allowed one to explore a domain's AD structure and get important details. I forget the name but am pretty sure it is in something like the "Windows Server Administration Pack" (or similar). I don't have time today to go looking it here...but maybe tomorrow or monday.

Sorry I can't get more to you today...

Stu
[ November 09, 2006: Message edited by: Stu Thompson ]
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Anyway thanks Stu. My current requirement has changed. Due to some security issues, I was asked to get openldap and connect to ADS using openldap. Currently I am working on it and will let you know.

Thanks,
Visu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stu,

The requirements have changed again. Using IIS, I am supposed to do the Windows Authentication.But I have done the necessary work on LDAP. Inorder to connect to an Active Directory server, a username and password is required, which is configured in the slapd.conf file. Due to security reasons anonymous access is disabled on ADS. Once we connect to the ADS, we can query the information. An user information is stored in the format:

dc:myCompany
dc:com
o:myCompany
ou:department
sn: sur name
uid : user id
email : mail address

We have to specify the search string as userSearch : {uid(0)}. This carries the username to the ADS and if it exists, then validates the password.

If we use OpenLDAP as a proxy server, we have to specify an entry in the ADS ldap-proxy and we will have to map the attributes to the ADS. Using slurpd.exe, we can replicate the data in ADS to OpenLDAP server and using slapd.exe, we can add entries to the OpenLDAP server.

Currently, I am working with configuring IIS with tomcat, enable the windows authentication in IIS, and get the username using the request header and if the windows authentication fails, forward to another page. If we have any useful links on this, please let me know.

Thanks in advance,
Visu
 
Stu Thompson
Hooplehead
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,

Wow. That sounds more complex than I would have expected, but like mentioned earlier...I have not actually implemented this myself therefor my opinion is suspect.

E.g.: I would have expected that the candidate user's login credentials would be used to access the ldap server or use an account setup for specially for tomcat rather than anon access. Maybe I just don't understand something here but I would think you could do this in a secure manner. It happens

Also, using IIS as a proxy seems unnecessary...unless that is it is there already for other purposes.

Question: Are you administrator's hostile towards non-MS platforms?

Regardless, let us know how you get on and what you learn. This is all interesting stuff!

Stu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stu,

I have encountered a peculiar problem. I am able to retrieve the username, domain name using the following code directly on tomcat.

String auth = request.getHeader("Authorization");
if (auth == null)
{
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM");
response.flushBuffer();
return;
}
if (auth.startsWith("NTLM "))
{
byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
if (msg[8] == 1)
{
byte z = 0;
byte[] msg1 = {(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S', (byte)'S', (byte)'P',
z,(byte)2, z, z, z, z, z, z, z,(byte)40, z, z, z,
(byte)1, (byte)130, z, z,z, (byte)2, (byte)2,
(byte)2, z, z, z, z, z, z, z, z, z, z, z, z};
response.setHeader("WWW-Authenticate", "NTLM " +
new sun.misc.BASE64Encoder().encodeBuffer(msg1));
response.sendError(response.SC_UNAUTHORIZED);
return;
}
else if (msg[8] == 3)
{
off = 30;

length = msg[off+17]*256 + msg[off+16];
offset = msg[off+19]*256 + msg[off+18];
String remoteHost = new String(msg, offset, length);

length = msg[off+1]*256 + msg[off];
offset = msg[off+3]*256 + msg[off+2];
String domain = new String(msg, offset, length);

length = msg[off+9]*256 + msg[off+8];
offset = msg[off+11]*256 + msg[off+10];
String username = new String(msg, offset, length);

out.println("Username:"+username+"<BR>");
out.println("RemoteHost:"+remoteHost+"<BR>");
out.println("Domain:"+domain+"<BR>");
}
}

But when I am trying to access the same thing through IIS, i am getting null values. Please help me out.

Thanks in advance,
Visu
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stu,

I forgot one more thing. Can we map names to our applications. For e.g. http://127.0.0.1:8080/jsp-examples to http://home.abc.com,
http://127.0.0.1:8080/servlets-examples to http://home.xyz.com

Thanks in advance,
Visu
 
Ben Souther
Sheriff
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
visu Nekk
Javaranch tip:

If you are going to post more than a line or two of your code, wrap that
code in a set of UBB Code tags.
Doing so will help to preserve your code's indenting, making it easier to read.
If it is easier to read, more people will actaully read it and you will
stand a better chance of getting help with your question.
See UseCodeTags for more
help with UBB code tags.
 
visu Nekk
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stu,

I have a problem with request.getRemoteUser(). It's not returning anything not even null. I have tried all the possibilities. in jk2.properties, i placed an entry tomcatAuthentication=false. I even tried request.tomcatAuthentication=false. I have checked Anonymous Access and Integrated Windows Authentication in IIS. I did this because I don't want a login box to popup, but to retrieve the username using request.getRemoteUser(). Please help me out if I am missing out anything.

Thanks in advance,
Visu
 
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[ UD: Please don't post the same question multiple times. Since this is an old thread, let's continue the discussion in this duplicate post. ]
[ February 29, 2008: Message edited by: Ulf Dittmer ]
 
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Visu,
did you ever figure out how it worked? I'm facing the same problem. request.getRemoteUser is always null but I desperately need it.
Lars
 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm struggling with what may be a similar issue.

I've developed a web-application and tested it on Tomcat 5.5 on my workstation. Instead of adding a <Realm/> element to server.xml, I created the file META-INF/context.xml, with a <Realm/> element as follows:



This works fine on my workstation: any user can authenticate to that instance using their AD username and password. However, for production use, I tried to deploy it to a Tomcat 5.0.28 server that's already running another web-application. It appears that the realm definition in the webapp isn't being used: I can only log in with the admin username and password that are used to access the /manager application, and that user doesn't belong to any of the roles that are used to control access to my application.

Does anyone know if Tomcat 5.0 didn't support META-INF/context.xml, or if additional configuration needs to be done to support it?
 
reply
    Bookmark Topic Watch Topic
  • New Topic