Automatic logon to a web application (JSF on jboss-4.2.2.GA) using JCIFS NTLM HTTP Authentication

The goal was to be able to make users which are logged in on a windows domain to automatically authenticate with their windows credentials when starting a web application, and also to make this solution possible both for IE and Firefox. In other words, the user doesn’t have to enter user-name/password when starting a corporate web application.

The web-app is done in JSF (myfaces 1.1.5), the application server is jboss-4.2.2.GA and the library I use to “grab” the windows user is JCIFS NTLM HTTP Authentication version 1.2.17 (http://jcifs.samba.org/). I will try to give a step-by-step explanation to what I did to make this work, and I will point out the differences you need to do compared to JAAS authentication mechanism (which is commonly used with applications running on jboss).

  1. The first ting you need to do is to download and put the jcifs library (jcifs-1.2.17.jar – or newer version) into your JBOSS_HOME/server/<NAME-OF-SERVER>/lib -folder.
  2. In your web.xml, you need to apply the following:
    <filter>
    
    	<filter-name>NtlmHttpFilter</filter-name>
    
    	<filter-class>jcifs.http.NtlmHttpFilter</filter-class>
    
    	<init-param>
    
    		<param-name>jcifs.http.domainController</param-name>
    
    		<param-value>IP ADDRESS_OF_THE_DOMAIN_CONTROLLER</param-value>
    
    	</init-param>
    
    	<init-param>
    
    		<param-name>jcifs.smb.client.domain</param-name>
    
    		<param-value>NAME_OF_DOMAIN</param-value>
    
    	</init-param>
    
    	<init-param>
    
    		<param-name>jcifs.smb.client.username</param-name>
    
    		<param-value>A_USERNAME_IN_ACTIVE_DIRECTORY</param-value>
    
    	</init-param>
    
    	<init-param>
    
    		<param-name>jcifs.smb.client.password</param-name>
    
    		<param-value>PASSWORD_FOR_THIS_USER</param-value>
    
    	</init-param>
    
    	<init-param>
    
    		<param-name>jcifs.util.loglevel</param-name>
    
    		<param-value>3</param-value>
    
    	</init-param>
    
    </filter>
    
    <filter-mapping>
    
    	<filter-name>NtlmHttpFilter</filter-name>
    
    	<url-pattern>/*</url-pattern>
    
    </filter-mapping>

    For the jcifs.http.domainController you specify the ip-address of the domainController you are authenticating against, e.g. 192.168.1.100.

    For jcifs.smb.client.domain you specify the domain that the users are logging in to. If you are uncertain about this check the logon-box in windows (XP login to domain) and write the domain name as its written here.

    In some examples on the net the jcifs.smb.client.username and jcifs.smb.client.password are not included. These are used for pre-authentication, think of it as a user that has access to the active directory so that it can retrieve information about the other users trying to log in. My experience is that if I leave out these two parameters, it works fine for the first user logging in, but for the first user only. When the second user logs in you get a 0xC0000022: jcifs.smb.SmbAuthException in the server log, and the negotiation of user-name/password fails. Including those parameters solves this issue. You could perhaps create a “dummy user” in the Active Directory just for this purpose (if you have administrator rights), if not use any other user of the AD.

    At least when trying to get this up and running I would recommend a logging-level set to 3. And of course you would set the url-pattern of the filter according to the path of the resources you want to protect, e.g. <url-pattern>/myJsps/*</url-pattern>

  3. If you are used to restricting access to your web application, you might have something like this in your web.xml:
    <security-constraint>
    
    	<web-resource-collection>
    
    		<web-resource-name>PROTECTED AREA</web-resource-name>
    
    		<description>Require users to authenticate</description>
    
    		<url-pattern>/*</url-pattern>
    
    	</web-resource-collection>
    
    	<auth-constraint>
    
    		<role-name>SOME_ROLE</role-name>
    
    	</auth-constraint>
    
    </security-constraint>
    
    <login-config>
    
    	<auth-method>BASIC</auth-method>
    
    	<realm-name>MY_NAME</realm-name>
    
    </login-config>
    
    <security-role>
    
    	<role-name>SOME_ROLE</role-name>
    
    </security-role>

    And then you would also have a security-domain set up in jboss-web.xml that points to an application-policy in login-config.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN"
    
    "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
    
    <jboss-web>
    
    	<security-domain>java:/jaas/MY_APPLICATION_POLICY</security-domain> -->
    
    	<context-root>/MY_CONTEXT_ROOT</context-root>
    
    </jboss-web>

    To be able to use the security filter with success, you would need to remove all of the settings related to security and JAAS. Remove the <security-constraint> (including children) , <login-config> and <security-role> tags from web.xml, and also delete the line specifying the <security-domain> in jboss-web.xml

  4. All the settings server-side are done now, what remains is a very simple configuration of the client/web browser. You need to tell your browser that the host/site you are trying to reach should be considered a trusted site. If you don’t do this, the browser would pop up the usual login-dialog and ask for username and password.
    • Enable it in IE:Go to tools->Internet Options->SecuritySelect Local Intranet icon and press “Sites”Press “Advanced”Fill in the url to the host of your application and press add. (Do not use the full application path or port settings, only the host address – for example: http://192.168.1.100)
    • Enable it in Firefox:Type about:config in the url-barLocate the key network.automatic-ntlm-auth.trusted-urisAdd the url to the host in the value-field. If there is other urls specified, separate them with a comma.
  5. If you now try to start your application, you should be automatically logged in with your windows user. The server log should say something like this if you have a successful authentication:
    [STDOUT] NtlmHttpFilter: THE_DOMAIN\user_name successfully authenticated
    
    against 0.0.0.0<00>/IP_OF_DOMAIN_CONTROLLER

I hope this overview can be helpful, but of course there are situations and special cases that I haven’t covered here. I would have to point you to the documentation and the FAQ on the homepage of the JCIFS library (see link in the start of this post). Still, I spent some time sorting out configurations, parameters and mistakes, so hopefully this will give others a shorter path to the goal.

Good luck!

Advertisements

7 Responses to “Automatic logon to a web application (JSF on jboss-4.2.2.GA) using JCIFS NTLM HTTP Authentication”

  1. Eric Says:

    Hi,
    I am having problem setting up the session replication for JCIFS on JBoss Clustering.

    Here is my environment:
    Web Server: 1 X Apache 2.2.8 (mod_jk 1.2.26 for load balancing) on SUN Sparc T2000 Solaris 10
    Application Server: 2 X JBoss 4.2.2 GA (Clustering) on SUN Sparc T2000 Solaris 10
    JCIFS: 1.2.18

    The error I have is that JCIFS.UniAddress is not Serializable and not able to replicate the session for it.

    I have read some of articles on-line and it all mentioned about not able to get the load-balance/clustering to work properly on JCIFS.

    Is there any way to make it work? Thank you very much.

  2. roneiv Says:

    Eric,

    I’m sorry to tell you that unfortunately I can’t help you with this issue. I have no experience at all running clustered Jbosses, and have never tested JCIFS for more than one jboss instance.

    I guess you could try to have a go and modify the JCIFS.UniAddress and implement Serializable, but probably you have already thought of that or you might have read about others that failed doing it.

    Hope you will find your solution!

    Regards,

    Eivind

  3. Abhijit Says:

    HI

    How to handled jcifs.smb.SmbAuthException in web application. I want to redirect user to some other login page if he is not authenticated using his domain name and password.

    Thanks

  4. roneiv Says:

    Hi Abhijit,

    Sorry for not having replied earlier, I’ve been away on vacation for some days 🙂

    But when it comes to handling the SmbAuthException I’m not that experienced, but I suggest you to have a look at this site:

    http://jcifs.samba.org/src/docs/authhandler.html

    Here they describe a way to handle SmbAuthExceptions.

    Hope this can help you!

  5. Sushil Says:

    Hello,
    Thank you for posting this article.
    Can you please let me know as to how can I retrieve user’s e-mail (associated with his account) once he’s authenticated? For example, if user xyz has logged in to domain mydomain then I need to fetch xyz@mydomain.com

    Thanks!

  6. thewonggei Says:

    Thanks for your post, it was helpful in pointing me in the right direction. However, according to the JCIFS FAQ, you can no longer use JCIFS the way you suggest (http://jcifs.samba.org/src/docs/faq.html#ntlmhttpauth). The JESPA library that is suggested in the FAQ looks like a much better option.

  7. Skyhan Says:

    I wish I had seen this article earlier. Can the above described methods be applied directly to Tomcat (6)?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: