Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

« Previous Version 4 Next »

A Java SE application or a Tomcat server runs under a native operating system userid. When it uses files and other local resources, it does so under the authority of that local system login. However, when an SE application uses a network service (say a database through JDBC), it has to provide a separate userid/password login to the remote server. A Web application running under Tomcat has the reverse problem, obtaining the identity of the remote user in order to access a personal profile or make access control decisions.

Shared Authentication

CAS is a Single Sign-On mechanism. The user logs on once to the CAS server and identifies himself though that one server to all the applications on the network. However, CAS can only be used by Web based applications that can be adapted to use its protocol. When you cannot use SSO, then you still want to avoid ending up with a dozen different systems each with its own set of userids and passwords.

The next best alternative is a network based system of shared authentication. You select a reliable, secure system to hold the userid/password data. It must expose a network API that allows the password validation to be done by lots of different systems and languages. Then each system may provide a login form where the user has to enter a userid and password, but the validation is done centrally.

Back in the old days it was popular to validate passwords using the Novell Netware systems, or the Microsoft LAN Manager, or Unix NIS. However, modern systems tend to choose either Kerberos 5 or LDAP. Both of these protocols are supported by Active Directory, and most systems and languages have client support for one or both of them. Kerberos is inherently secure, while LDAP can be made secure if it runs over SSL.

Rather than coding specific Kerberos or LDAP authentication logic for every application, Unix systems developed the idea of a Pluggable Authentication Module (PAM).  There is a single standard programming interface that every application can use. Behind that interface, a system administrator can plug in one or more service provider modules that use Kerberos, LDAP, a database system, or some network appliance to validate the userid and password and maybe return information about the user.

Shared authentication becomes more complicated as authentication itself becomes more involved. In the old days you just used passwords and that was good enough. In the new world it may be necessary to establish identity by using passwords and some physical device that plugs into a USB port. Pluggable authentication has to be able to extend to these more complicated environments.

JAAS - Pluggable Java Authentication

JAAS became the Java SE version of the PAM idea. Standard Java releases since 1.4 have included the javax.security.auth.* packages. They work like JDBC in exposing a single standard front set of classes that are extended by adding external libraries to the classpath that provide additional classes implementing a service provider interface. JDBC is extended by libraries of database drivers, while JAAS is extended by login providers.

Out of the box, Sun provides classes to do the Kerberos 5 and LDAP login function. Those are probably the best choices for any institution planning to use standard internet protocols and network based software solutions. However, hardware manufactures selling USB dongles and Smart Cards may also sell network appliances that authenticate users of these hardware devices. JAAS provides a standard interface that can be used for even exotic requirements. The vendor simply provides a JAR file with classes that implement the JAAS service provider interface, and then the system administrator can configure the vendor authentication as easily as one of the standard Sun classes.

The first time someone learns about JAAS, they probably use it to validate a userid and password against a standard network server (like Microsoft AD). At first, the API seems more complicated than you expect:

  1. The Java code creates a Callback object that holds the userid and password. This object will be passed to JAAS, which will call it in the middle of login to obtain the userid and password parameters.
  2. Then the program creates a LoginContext object passing a character string naming an external JAAS configuration parameter bundle in one of the login configuration files and the Callback object.
  3. The login() method of the LoginContext authenticates the userid and password using whatever service provider class was specified and parameterized by the configuration bundle. 

The reason for the callback class is that userid and password are not the only credentials someone can use to prove their identity. In addition to password, a Kerberos 5 KDC can authenticate using a keytab file containing the secret private key derived from the password. Keytab files are a common way to identify not people, but specific services residing on machines in the network. When the private key is stored on a USB device, then the callback provides an opportunity for a special Java driver to use the device to prove identity.

JAAS is different from most of the standard Java services in that it is not designed to work exactly the same on all systems. The "write once run anywhere" contract applies to Applications.The whole idea of JAAS was to remote protocol coding and local server configuration from the Application. What is left is just the request interface which is portable across all systems because it does almost nothing itself. The Application does not depend on whatever happens behind the interface. While the Sun class that does LDAP authentication is available on all systems, a vendor supplied plug-in that uses a network appliance could be unique to a small set of customer institutions, and an experimental authentication system may exist in only one place. So JAAS plug-ins are not expected to be 100% pure Java and completely system independent.

There are also some extra features to JAAS, particularly when it is used in Kerberos 5. However, before these features can be understood, we need to probe a bit more into the parts of the JAAS API that people do not learn when they are just using it to verify a password.

JAAS Login Configuration

A JDBC database driver requires no special configuration, but then the client application program has to supply the URL to the server and the connection parameters. JAAS is designed to remove the entire authentication process from the application and move it to the system administrator. As a result, the JAAS "login configuration" looks something like the configuration of a Spring Bean or a Servlet Filter.

The starting point of JAAS configuration is a bundle of parameters that specifies the fully qualified name of a plug-in class that implements the JAAS Service Provider Interface (SPI). That is followed by a optional set of property values that configure the instance of that class object.

myauth {   
    com.sun.security.auth.module.LdapLoginModule REQUIRED   
        userProvider="ldaps://yu.yale.edu/dc=yu,dc=yale,dc=edu"   
        userFilter="(&(sAMAccountName=\{USERNAME\}))"
        useSSL=true;
    }

This configuration bundle selects the standard Sun LDAP plug-in module supplied with every JRE. It provides a URL with server name and starting search location, and an LDAP query that can be used to locate an LDAP User object given a Netid argument (represented by the {USERNAME} variable.) With this configuration, JAAS will go to the Yale Active Directory, search for a legacy userid matching the userid supplied by the JAAS client application, and then validate the password against the unique object returned from the search. Using a search gets around the problem when some departments create userids in their own OU instead of using the common Users container. The bundle has been given the name "myauth". A client program can pass this name to JAAS to select this particular configuration and authenticate using the Yale AD.

This particular file format is used by the default JAAS services provided by J2SE. However, under the covers the com.sun.security.auth.module.LdapLoginModule is just a Java class that implements the JAAS SPI interface, and the interface specifies how the named parameters should be set in an instance of the class. The standard JAAS implementation can be hijacked by a particular container environment (Spring, JBoss, ...) that exposes the same API to the client programs and uses the same plug-in modules, but uses a different configuration file and maybe adds some additional processing in the middle. So be prepared to see a version of this same configuration bundle expressed in XML, and possibly in different XML formats in different systems.

One or more of these named bundles of classname+parameters can be added to a JAAS "login configuration file". There are three places you can find configuration files:

One or more configuration files using the format in the example above can be specified in the Java Runtime itself. Specifically, the lib/java.security file has a section :

#
# Default login configuration file
#
#login.config.url.1=file:${user.home}/.java.login.config
login.config.url.1=file:${java.home}/lib/security/jaas.conf

 In this example, a login configuration file named "jaas.conf" located in the JRE lib/security directory has been added to the standard JVM environment and will be available to any program that uses this JRE.

The container that you use may provide its own JAAS configuration, sometimes in its own format. In JBoss, for example, the default server configuration contains a JAAS configuration in a JBoss XML format in the server/default/conf/login-config.xml file. Expressing the previous bundle of parameters in JBoss syntax would look like this:

   <application-policy name="myauth">
    <authentication>
      <login-module code="com.sun.security.auth.module.LdapLoginModule" flag="required">
        <module-option name="userProvider">ldaps://yu.yale.edu/dc=yu,dc=yale,dc=edu</module-option>
        <module-option name="userFilter">(&(sAMAccountName=\{USERNAME\}))</module-option>
        <module-option name="useSSL">true</module-option>
      </login-module>
    </authentication>
  </application-policy>

The third possibility is that the individual application may have a JAAS configuration file embedded in it. Of course, this packaging violates the original idea of separating authentication as a system administration function from the application programmer's domain, but not all institutions have Java literate system administrators.

What's in a Name?

 JAAS configuration offers enormous flexibility, but this leaves an ambiguity that should be resolved by institutional policy. If it is not given some global thought, you leave room for inconsistency and confusion.

During application development, it makes sense for system administrators to create a set of pre-packaged JAAS configuration parameters representing the different supported types of authentication and different back end servers that the local environment supports. This suggests names like MITKerberosAuth or ActiveDirectoryLdapAuth. The application programmer can regard these names as configured system services and use them to get started.

However, when an application is deployed in production, the JAAS design seeks to completely separate the authentication mechanism from the application code. Even using a name that indicates a particular protocol or back end service contradicts this design objective. This produces two plausible naming conventions.

An application could use its own name as the JAAS configuration bundle name. Thus the CAS Server could specify "cas-server" as the bundle name. This is a good default for a product that is distributed to lots of different institutions that have to make up their own local policy about what authentication mechanism to use, but if the default is not changed then the typical institutional JAAS login configuration file will have dozens of identical configuration bundles differing only in the the application name at the start of the bundle.

Alternately, an institution could specify a small number of bundle names representing the generic type of authentication (an authentication design pattern) that an application might select (SingleSignOn, SingleSignOnWithProxy, SharedAuthentication). Note that these names do not reflect a particular protocol or server, but neither are they limited to a particular application. Unfortunately, these design patterns have not be assigned industry standard names, so this preferred approach will probably vary from institution to institution.

  • No labels