Secure Web Authentication
By Gordon Mathis
Introduction
An important development for the Novell Modular Authenticate Services (NMAS) is a browser plug-in that allows you to authenticate to any Java-enabled Web site using any NMAS method installed under the NMAS client. This makes it possible to authenticate to a Web site using a biometric or token device instead of just a password.
Imagine being able authenticate to your bank account with a fingerprint instead of just a password. Or, maybe you prefer a fingerprint and a certificate stored on a smart card. This is all possible today using the NMAS browser plug-in, which takes immediate advantage of any Novell or third-party NMAS method. No additional development is required to use the plug-in for existing methods. Currently there is a plug-in for the Microsoft Internet Explorer and Mozilla Firefox browsers.
All that is required to get this working is a Windows CAB file and a few tags added to an existing JSP or Java Servlet.
A sample servlet, including source code, is located at http://www.novell.com/developer/secure_web_authentication_servlet.html. This article outlines the requirements for this sample servlet and illustrates a few screen shots demonstrating this NMAS option.
Servlet Components
web.xml
I will begin by discussing the web.xml file. You will notice that this is a typical deployment descriptor for a servlet. The LDAP_HOST and NMAS_LOGIN_SEQUENCE parameters have been added to make the servlet easier to configure. The LDAP_HOST parameter must contain the IP Address of the Novell eDirectory server. By simply changing the NMAS_LOGIN _SEQUENCE parameter, you can control which NMAS sequence to use when authenticating. Keep in mind that a NMAS sequence contains one or more NMAS methods.
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name> WebAuthServlet</display-name> <servlet> <description></description> <display-name>NmasAuth</display-name> <servlet-name>NmasAuth</servlet-name> <servlet-class>com.novell.security.NmasAuth</servlet-class> <init-param> <param-name>LDAP_HOST</param-name> <param-value>137.65.136.37</param-value> </init-param> <init-param> <param-name>NMAS_LOGIN_SEQUENCE</param-name> <param-value>NDS</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>NmasAuth</servlet-name> <url-pattern>/NmasAuth</url-pattern> </servlet-mapping> </web-app>
init Method
The init method of this servlet reads the parameters from the deployment descriptor into global variables and makes them available to the doGet and doPost methods.
public void init() { ldapHost = getInitParameter(LDAP_HOST_TAG); loginSequence = getInitParameter(NMAS_LOGIN_SEQUENCE_TAG); }
goGet Method
There are several important items in this doGet method. First is the inclusion of the nmasclnt.js, which contains the required JavaScript functions. Next is the object id element, which identifies the browser plug-in or the NMASWeb.cab file.
Next is the JavaScript Login function that gets called when the form is submitted. Notice that there are several hidden input elements used by the Login function.
Finally there is an additional form with an id attribute of loginStatus used to return the login results. Notice that the only element of this form is hidden and it is submitted by the Login function found in the nmasclnt.js.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Secure Web Application Authentication</title>"); out.println("<script type='text/javascript' src='" + request.getContextPath() + "/nmasclnt.js'> </script>"); out.println("</head>"); out.println("<body>"); out.println("<object id='NmasPluginID' classid='CLSID:79EE9C76-2CE6-450F-9842-2CC6191DA070' codebase='" + request.getContextPath() + "/NMASWeb.cab#version=1,0,1,0' height='0' width=’0’></object>"); out.println("<form onsubmit=\"Login('NmasPluginID', 'USER_ID', 'treeNameID', 'loginSequenceID', 'postUrlID'); return false;\">"); out.println("<input type='hidden' id='treeNameID' name='treeName' VALUE=/>"); out.println("<input type='hidden' id='loginSequenceID' name='loginSequence' VALUE='" + loginSequence + "'/>"); out.println("<input type='hidden' id='postUrlID' name='postURL' VALUE='http://"+ldapHost+ ":8080/" + request.getContextPath() + request.getServletPath() + "'/>"); out.println("LDAP User DN: <INPUT id='USER_ID' type='text' name='username' value='cn=gmathis,o=novell' size='35'>"); out.println("<INPUT type='submit', value='Login'>"); out.println("</form>"); out.println("<form id='loginStatus' name='loginStatus' method='POST' action='http://" + ldapHost + ":8080/WebAuthServlet/NmasAuth'/>"); out.println("<input type='HIDDEN' id='NMASReturnCode' name='NMASReturnCode' value=/>"); out.println("</form>"); out.println("</body>"); out.println("</html>"); }
doPost Method
When the user clicks the Login button on the login window the servlet's doPost method is called a number of times by the browser plug-in. Because this method is called numerous times for a single NMAS authentication, it is necessary to maintain a state variable. In the code sample notice that servletState variable changes from INITIAL to LOGIN_IN_PROCESS, and finally LOGIN_COMPLETE.
In the INITIAL state, we create an NMASCallbackHandler and LoginMonitor thread, which basically does the LDAP bind, and then sets the servletState to LOGIN_IN_PROCESS. In the LOGIN_IN_PROCESS state, we simply call the processHttpRequest and return until NmasLoginComplete is detected. After the NmasLoginComplete is detected, we display the login results and reset the servletState back to the INITIAL state. A failed login will also register an NmasLoginCompelete, in which case the routine goes back to the INITIAL state and must process the errors from the browser plug-in.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if(servletState == INITIAL) { String version = request.getParameter(NMAS_PLUGIN_VERSION_TAG); System.out.println("NMAS Plugin Version = " + version); ldapDN = request.getParameter(NMASClient.NMAS_USER_DN_TAG); //"username"); System.out.println(ldapDN); ldapPort = 389; callbackHandler = new MyCallbackHandler(request); myLoginMonitor = new MyLoginMonitor(); if((ldapHost != null) || (loginSequence != null)) { myLoginMonitor.startLogin(ldapDN, loginSequence, ldapHost, ldapPort, ssl, callbackHandler); servletState = LOGIN_IN_PROCESS; } else { // Return an error page } } if(servletState == LOGIN_IN_PROCESS) { callbackHandler.processHttpRequest(request); if(!callbackHandler.isNmasLoginComplete()) { callbackHandler.generateHttpResponse(response); } else { servletState = LOGIN_COMPLETE; int nmasReturnCode = callbackHandler.getNmasRetCode(); } } if(servletState == LOGIN_COMPLETE) { callbackHandler.processHttpRequest(request); nmasLoginResult = myLoginMonitor.getLoginResult(); // This method blocks until MyLoginMonitor login thread completes // Determine if login was successful // If successful, then do what you need to do with the authenticated LDAP connection servletState = INITIAL; // If you want to reuse this instance of the servlet response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.write("Login Complete (NMAS Return Code = " + nmasLoginResult.getNmasRetCode()" )"); } }
Installing Plug-in Components
Use the following procedures to try the NMAS browser plug-in:
- Install the latest Novell eDirectory server, which includes the NMAS server and the latest Novell Client, which includes the NMAS client components. If you need help setting this up, refer to the instructions for installing and testing eDirectory at http://www.novell.com/coolsolutions/feature/16005.html. This setup should allow you to authenticate using the NDS method.
- Downloaded and install JDK 1.4.x http://java.sun.com/j2se/1.4.2/download.html. The Novell LDAP NDK currently requires JDK 1.4.x.
- Download and install Apache Tomcat 4.1 http://tomcat.apache.org.
- Place the WebAuthServlet.war file from the forge in the <tomcat>\webapps directory and execute the <tomcat>\bin\startup.bat. Tomcat will expand the WAR file to create the <tomcat>\webapps\WebAuthServlet directory structure.
- Edit the <tomcat>\webapps\WebAuthServlet\WEB-INF\web.xml file and modify the IP address to reflect the correct eDirectory server's IP address.
- Restart Tomcat:
<tomcat>\bin\shutdown.bat <tomcat>\bin\startup.bat
- Open and a browser and browse to http://localhost:8080/WebAuthServlet/NmasAuth.
- Modify the user DN and then click the Login button.
- If everything is setup correctly and the user's DN is located in the directory, the user will be prompted for their NDS password. Notice that this dialog is not part of the web page by moving the dialog window. Simply enter the NDS password and click OK.
- Notice the return code is 0, which indicates a successful authentication.
- Modify the user DN and then click the Login button.
If you have another NMAS method installed, try changing the NMAS_LOGIN_SEQUENCE parameter in the <tomcat>\webapps\WebAuthServlet\WEB-INF\web.xml file from NDS to another sequence name, and logging in as a user whose credentials are enrolled in eDirectory. I used the SecuGen sequence and was prompted with the following fingerprint dialog allowing me to authenticate to my web site via a biometric. Cool ah!
Summary
The NMAS browser plug-in allows users to authenticate to Web sites using something besides a password. This feature provides an additional level of security because it ensures secure authentication from a users biometric or token device attached to their workstation all the way to the back end directory server, instead of from just the Web server to the directory server (or workstation to server if using SSL). Ensuring that users are who they claim to be. Couple this with NMAS's ability to do multi-factor and graded authentication and you have a very secure Web site.