NTLM Authentication in Java
Join the DZone community and get the full member experience.
Join For FreeIn 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 <span style="position: relative; width: 190px; height: 10px;">"); out.println(s + "</span>"); } %>
From http://scrtchpad.wordpress.com/2011/08/04/ntml-authentication-in-java/
Opinions expressed by DZone contributors are their own.
Comments