NTLM Authentication in Java

By | 4 August, 2011

In one of my previous lives, I used to work in Microsoft and there this word – NTLM (NT Lan Manager) was something that came to us whenever we used to work on applications. Microsoft OS have always provided us with an inbuilt security systems that can be effectively used to offer authentication (and even authorization to web applications).

Many years back, I moved over into Java world and when I was asked to carry out my very first security implementation, I realized that there was no easy way to do this and many clients would actually want us to use LDAP for authentication and authorization. For many years, I continued to use that. And, then one day in a discussion with a client, we were asked to offer SSO implementation and client did not have an existing setup like SiteMinder. I started to think about if we can go about using NTLM based authentication. The reason that was possible was because the application we were asked to build was to be used within the organization itself and all the people were required to login into a domain.

After some research, I was able to find out a way we could do this. We did a POC and showed it to the client and they were happy about it. What we did has been explained below:

  • Wrote a Servlet which was the first one to be loaded (like Authentication Interceptor). This servlet was responsible for reading the header attributes and identify the user’s Domain and NTID
  • Once we had the details; we sent a request to our Database to see if that user is registered under the same domain/NTID
  • If the user was found in our user-database we allowed him to pass through
  • And then roles and authorization for user was loaded

Basically, we bypassed the “Login Screen” where the user was entering the password and used Domain information. Please note that it was possible for us because the Client guaranteed that there was this domain always and all users had unique NTIDs. Also, that it was their responsibility to shield the application from any external entry points where someone may impersonate the Domain/ID.

If you are interested, you can refer to the code below:

<%@ page import="sun.misc.BASE64Encoder" %>
<%
String auth = request.getHeader("Authorization");
String s = "";

//no auth, request NTLM
if (auth == null)
{
        response.setStatus(response.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM");
        return;
}

//check what client sent
if (auth.startsWith("NTLM "))
{
        byte[] msg =
           new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
        int off = 0, length, offset;

        if (msg[8] == 1) {
            off = 18;

            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};
            // send ntlm type2 msg

            response.setStatus(response.SC_UNAUTHORIZED);
            response.setHeader("WWW-Authenticate", "NTLM "
               + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());

               return;
        }
        else if (msg[8] == 3) {
                off = 30;
                length = msg[off+17]*256 + msg[off+16];
                offset = msg[off+19]*256 + msg[off+8];
                s = new String(msg, offset, length);
                // print computer name // out.println(s + " ");
        }
        else
        return;

        length = msg[off+1]*256 + msg[off];
        offset = msg[off+3]*256 + msg[off+2];
        s = new String(msg, offset, length);
        //domain//out.println(s + " ");
        length = msg[off+9]*256 + msg[off+8];
        offset = msg[off+11]*256 + msg[off+10];

        s = new String(msg, offset, length);
        out.println("Hello  "); out.println(s + "");
}
%>

8 thoughts on “NTLM Authentication in Java

  1. Abinash

    Hi…The same thing i m implementing but i m struggling with a thing that as per my requirement is the ntid passowrd should not be cached in the user machine…is there any way for this..please help……………………………………………

    Reply
    1. Kapil Viren Ahuja

      Abinash – can you provide more details on what you want to do // The whole idea of integrating with an Active Directory is that you are should not need to store any credentials.

      Reply
      1. Reddy

        Hello Kapil, I am trying to see how we can integrate NTLM authentication with AD. If you have any POC, can you share Since I need to see how this works?

        Thanks
        Reddy

  2. Chandan Arora

    Hello Kapil,

    Thanks for putting this aricle. The solution mentioned here has come as a great help to me. I have learnt a lot from you, thanks for all help and guidance.

    Please keep posting such interesting things.

    Best,
    Chandan Arora

    Reply
  3. vempati suresh kumar

    We have implemented NTLM with waffle using spring security filter my web application.

    The following scenario is not working. is waffle supports below scenario or not?

    The application is deployed in Tomcat server in X domain.The application is getting used for different users which are in other network and those are Work group computers. (Application is deployed in some central location and some child organizations, i.e, y, z, which are not in same X domain will try to access the application).

    When we try to access tomcat URL, with the organization , application is asking for user credentials and page is loading properly once after authentication. But when we try to access application from Y Organization, where computers are in WorkGroup instead of domain, the application is asking for credentails. Even when we provide valid credentials, application page is not loading.

    After 3 attemps of login pop-up getting Http 401 message.

    is waffle supports my scenario or not. If not, How i can implement windows authentication in such case. ( I can not use IIS WIndows authentication as some organizations use ADFS authentication in my tomcat application).

    Please suggest.

    Reply
    1. Kapil Viren Ahuja Post author

      I have never tried this solution with AD or in this scenario. However, the solution depends on reading the headers and parsing them. Have you tried logging what the client is sending to server in the scenario in which this is not working. If you can share those with me, maybe i can help.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.