This subject area keeps poking its head back up, and I know it's still tough for new developers to grasp, so I thought I should publish my old notes and pointers. These mostly deal with applications under JBoss and accessing Active Directory (either as an LDAP server or with kerberos) since that was our primary deployment environment.
I will update these as I can. I know that some new projects (like JOSSO) have emerged since I did my original research. One or more of these may make implementing a new solution much easier than it was when I started.
Centralized Authentication of Web Applications
When someone talks about using a central system like an LDAP or Active Directory (AD) server to maintain user information, s/he is thinking about one of three concepts, Individual Application Authorization, Manual Single Sign On (SSO), or Automatic SSO. Before discussing these, let's make sure we understand the two parts of securing a web application.
Authentication vs Authorization
There are two key parts to letting a user into an application, authentication and authorization. Authentication determines who a user is (usually using a user name & password). Authorization determines what a user is allow to do within an app. Authorization is normally determined by checking role or group membership in some manner.
It is often the case that the phrase "authenticate a user" is used to refer to both authentication and authorization since almost all security procedures do both. Be warned that there is no standard for doing authorization, though there was a proposal in front of the kerberos standardization committee to add group/role information to kerberos tickets when I last looked into this in 2007. It may have been adopted since then.
Concept 1: Single Storage, Repeated Sign-On
This means enabling one or more web applications to use a directory server (LDAP in general or Active Directory (AD) specifically) to authenticate and authorize a user in an application. Every time a user wants to access a different application (on the same server or a different server), the user needs to enter login information. However, a user's credentials are the same for all applications, making it easier for the user to remember and easier for an administrator to manage.
Generally speaking, this is pretty easy to implement. There are a many code samples on the net. A simple one that uses JNDI (the easiest way to do it) is on the OpenLDAP site. This example explains the standard way to authenticate a user against an LDAP server using two binds, one as a system account to verify an account exists and one as the actual user account to verify password info. The code to do it against an AD server is very similar.
JBoss also has a built in mechanism that can do this. For a full explanation, see the Security on JBoss chapter of the JBoss admin guide (mostly sections 8.2-8.4). If you don't want that much detail, the JBoss Getting Started doc with its sample application also talks about basic security setup. Two other sources of info:
JBoss Wiki note on LdapExtLoginModule
The note covers LDAP configuration in general, but gives a specific example about AD near the bottom. The example didn't quite work when using a test Active Directory server that I had setup. I added the following block in the login-config.xml file in the $JBOSS_HOME/server/default/conf directory to create a security context that worked for us:
<login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required">
<module-option name="bindDN">cn=Binding Account,cn=Users,dc=test,dc=company,dc=com</module-option>
Add the following line to the jboss-web.xml file of a web application running under jboss, it will force authentication against the AD server:
Finally, you also need to add <security-constraint>, <login-config>, and <security-role> blocks to the web.xml file for the web app.
<security-constraint>Role Based Access Control (RBAC) with JBoss and LDAP
<description>Require users to authenticate</description>
<description>Only allow Authenticated_users role</description>
<description>Encryption is not required for the application in general.
This is an example explaining how easy it is to plug into JBoss's authentication framework. It does a lot more work than needed to use the built in LdapLoginModule described above. It is intended more to show how to write your own module. Be aware that the directory configuration used in this example does not match the structure of an AD server and will not work with the LdapLoginModule. The example uses user, group, and role concepts while the LdapLoginModule combines the group and role concepts.
Concept 2: Manual Single Sign On (SSO)
This SSO concept means that once a user has authenticated against a particular server for one application, she can access other applications/services on that server without having to re-enter a password. Careful of the phrase "on that server." The implication is that all of services themselves reside on a single server (i.e. under a single JBoss instance). This is not necessarily the case. There are SSO solutions that can be integrated with a web application to allow it to run all of its authentication steps through another server. See the Yale CAS System and some further notes on it below.
An old listing of many SSO solutions for both web and fat-client applications and WS/SOA (Web Services/Service Oriented Architecture) apps is here. Yale's CAS and JBoss's built in authentication system were the most interesting to my group when I did the research because they did most of what we wanted. Others are more bare bones and require more work to implement, or are targeted at WS/SOA apps, or may work with LDAP in general, but not Active Directory specifically. A study of the CAS system and two others is here. I have not looked at the two other solutions.
The built-in JBoss security system (using the LdapExtLoginModule described above) does support SSO, though a small change must be made to the Tomcat server.xml file as detailed on the JBoss Wiki SSO page. This tweak may no longer be required with newer versions of JBoss.
A good example of how to use this system is on DeveloperWorks. A couple of notes on it:
- Requires HTTPS and some extra setup of Tomcat
- Does allow SSO for apps running on multiple servers. Those apps just have to be able to reach the CAS server.
- Unclear if it implements role-based access, or if it only checks that a user/pword are correct.
- Someone posted how to integrate SecurityFilter (a Java library we use to manage user authentication) with CAS on the CAS wiki.
The SSO systems described above do not use the authentication credentials that a user receives by logging into his computer to automatically access a web application. You might call this "Auto Single Sign On" authorization. While this is relatively easy to do in fat-clients with JAAS, there is no universally implemented standard for doing it with web applications. Until recently, the only way to do it through a browser was with Microsoft specific technology called Integrated Windows Authentication (IWA). This has historically been called NT Challenge/Response or NTLM authentication, though NTLM is only one authentication mechanism in IWA. IWA can use Kerberos as it's authentication mechanism as well. Kerberos is the default for Windows 2K and beyond. Compared to the three standard methods of authentication for web applications listed below (see User Login Authentication Schemes), IWA is similar to the Digest method in that the password is never sent over the wire. These pages gives a basic overview of how IWA works, with references to both NTLM and Kerberos authentication:
Only Microsoft products on both the client side (Internet Explorer) and server side (IIS) have full, built-in and auto-activated support for this type of authentication. However, other web browsers and web application servers can be configured/extended to support a standard that IWA is based on. The general term for this form of authentication is SPNEGO, the Simple and Protected Negotiation mechanism. When used in web applications, it is called "HTTP Negotiate" authentication. This is as opposed to "HTTP Form" or "Http Basic" authentication, the two most common types.
SPNEGO means Simple and Protected Negotiation. The negotiation part refers to the mechanism used to securely transfer user credentials from the client's browser to the web app server. There are two primary options out in the world now - kerberos and NTLM. NTLM is a MS Windows specific protocol that is used by client machines to connect to Windows NT domains. Starting with Windows 2000 Server and the introduction of Active Directory servers as domain controllers, kerberos became the default authentication mechanism, though NTLM is still supported. This is useful if you only have Windows-based web clients because you don't have to do any special configuration on the Active Directory server. If you want to use kerberos as the mechanism, you must add an entry to the Active Directory server for the web application host machine.
HTTP Negotiate Steps
When a web application tells a web client that Negotiate authentication is required, the client can determine what negotiation mechanism it wants to use. If the client is a Windows machine, the machine belongs to the Active Directory domain, and the user has logged into the client using a domain account, the web browser will first try to use kerberos. (Note that FireFox and Mozilla must have a preference setting changed to try kerberos. Internet Explorer will do it automatically.) The browser will attempt to obtain a kerberos ticket for the web application server from the AD domain controller. For this to work, AD must contain an entry for the web application server. If no such entry it present, the browser will revert to using NTLM as the authentication mechanism instead of kerberos. This will still happen without the user being prompted.
If the user is not logged in using a domain account (or Firefox/Mozilla is being used and has not been configured to use the negotiate authentication), she will be prompted to enter a login and password. Even though the login box looks like one you would see with BASIC authentication, the credentials are transferred in an encrypted NTLM block. Kerberos is not used. While NTLM is somewhat less secure than a full kerberos ticket exchange, it is much more secure than BASIC or FORM authentication, which transfers the user name and password in the clear.
Configuring Kerberos Negotiate Authentication
I'll save this for a later post. My notes for this are tuned toward the solution I ended up implementing, so I'll have to tweak them to be generally useful.
Random Tip: When testing kerberos - domain/realm must be entered in all caps - e.g. MYCOMPANY.COM. Otherwise you will get a "Pre-authentication information was invalid (24)" error.
User Authentication Schemes
The Sun webservices docs have a good summary of the standard types of authentication for web applications. Basic and Form based authentication are essentially the same from a security standpoint. They both send user name and password information in clear text to the server. Form authentication just lets you customize how it looks to the user in a web page.
Digest never sends the actual password across the wire. Instead, the server issues a "nonce" value (one-time, time-specific bit of data) to the client. The client then encrypts that with the users credentials (like an X.509 certificate), and sends back the username and encrypted result. The server can then use those to determine if the proper password/credentials were entered on the client side.
Here is where I got most of my understanding of kerberos, NTLM, and web-based security in general. Remember, I did this initial research almost 3 years ago, so some of these links may now be outdated.
Kerberos under Windows
Examples using GSSAPI to connect a client machine to a server
* http://forum.java.sun.com/thread.jspa?threadID=579829&tstart=300 - Note that this is not targeted at web app (or a web server). Rather, it is showing how a client app running on a machine that has a kerberos ticket in its cache (i.e. where the user has logged into the machine as a domain user) can use it to authenticate against an LDAP server for doing operations.
* http://forum.java.sun.com/thread.jspa?threadID=638537 - Uses GSSAPI to authenticate to a LDAP directory (rather than simple authentication). Note that this is only useful for fat clients (or a server)
* http://ackbarr.xoops.org/archives/2005/03/31/integrated-windows-authentication-in-firefox/ - How to change the FF installer to auto-enable the settings.
* http://davenport.sourceforge.net/ntlm.html - The unofficial bible for how NTLM authentication works. This does not tell you directly how Internet Explorer gets the security context from a user. It does contain a nice list of "Links and References" near the end.
* http://www.theserverside.com/news/thread.tss?thread_id=28101 - Thread on how to do NTLM in a Java web app
* http://forums.mozillazine.org/viewtopic.php?p=631269 - Mozilla thread on NTLM support
* https://bugzilla.mozilla.org/show_bug.cgi?id=17578 - Mozilla Kerberos support
* http://curl.haxx.se/rfc/ntlm.html - NTLM in detail - including info on POST behavior
Negotiate authentication in various other web application servers
* http://lists.samba.org/archive/jcifs/2004-July/003651.html- Tomcat and SPNEGO
o Related: http://lists.samba.org/archive/jcifs/2005-April/004939.html
* http://appliedcrypto.com - Tomcat and SPNEGO/Kerberos (costs $$$). Their offerings are almost entirely based on various open source projects that they have pieced together
* http://blog.sun.com/roller/page/wyllys/?anchor=kerberos_web_authentiation_with_apache - Apache Kerberos plugins
* http://rc.vintela.com/topics/apache/mod_auth_vas/- Another Apache Plugin