C.1. JAASJAAS is a standard Java extension in J2SE 1.4, and it provides pluggable authentication that gives application designers a wide choice of security realms:
JAAS supports single sign-on for an application. Rather than forcing the user to log in to a web site, and then log in again to a forum or a backend legacy system used by the application, JAAS coordinates all these steps into one central login event to help coordinate access to all systems that the user needs. We chose JAAS as the basis for our authentication strategy because:
C.1.1. JAAS Core Concepts, Classes, and InterfacesHere are the key pieces of the JAAS framework and the roles that they play:
C.1.2. LoginContextThe JAAS LoginContext authenticates a user. The LoginContext instantiates the LoginModule (s) (that log the user into the security realm) based on the contents of the LoginModule Configuration file. By storing the LoginModule setup information in a configuration file, you can change the LoginModule(s) without modifying the application. The LoginContext invokes the LoginModule(s) for an application, and acts as the controller for the logon process. If the application accesses multiple security realms, the LoginContext coordinates the logon process across multiple LoginModule(s) (one per security realm). C.1.3. LoginModuleThe LoginModule logs a user/Subject into a security realm based on their username and password. A LoginModule could interact with an operating system, a database, JNDI, LDAP, or a biometric device like a retinal scanner or touch pad. Application developers normally don't need to know very much about LoginModules because the LoginContext invokes them on behalf of an application. Thus your code never interacts with LoginModules. To add or remove a LoginModule used by your application, you only need to modify the LoginModule Configuration fileyour code remains unchanged. This indirection enables an application to be independent of the underlying security mechanisms used Although you could write your own LoginModule, doing so is usually unnecessary because of the abundance of quality third-party Open Source implementations available. You only need to know how to configure (in the LoginModule Configuration file) and deploy them for your particular runtime environment. If the Open Source LoginModule implementations don't provide all the functionality you need, you can either modify the code from that library or write your own LoginModule. Since this topic is outside the scope of this book, please see the JAAS LoginModule Developers' Guide (http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html) for further details.
We could easily configure the Tagish, Sun, or JBoss LoginModules and use them with the JAW Motors application. We chose the JBoss LoginModules because they're already bundled with JBoss and we don't need to configure any third party JARs. Even though we use LoginModules provided by JBoss, the application code remains vendor-neutral because:
C.1.4. CallbackThe Callback interface enables other JAAS components to retrieve user authentication information, such as usernames and passwords. The Callback implementations include:
The external application uses the NameCallback to hold the username and the PasswordCallback to hold the password. As you'll see in the next section, we use these Callbacks a bit differently than the standard JAAS documentation, so it works in a command-line application. C.1.5. CallbackHandlerThe CallbackHandler is an interface that enables LoginModules to retrieve authentication information such as a username and password entered by the user. The CallbackHandler is the most confusing part of the JAAS API because its whole design premise is that you don't have user authentication data yet, and that the application needs to query the user for this information. However, this type of user interaction flies in the face of the client application's design because the user already entered her username and password on the command line. The external client just needs to pass the user's data to the LoginContext. To make JAAS compatible with our application, we strip out the functionality that queries for a user name and password that you would see in a typical JAAS API tutorial. We'll implement a passive CallbackHandler that acts as a simple pass-through that holds only the username and password without querying the user for further information. The LoginModule(s) simply call the CallbackHandler's handle( ) method to retrieve the username and password that the user previously entered on the command line, as in Example C-1. Example C-1. MyPassiveCallbackHandler.javaimport javax.security.auth.*; import javax.security.auth.callback.*; // Simple placeholder that stores userName and password. public class MyPassiveCallbackHandler implements CallbackHandler { private String userName; private String password; public MyPassiveCallbackHandler(String userName, String password) { this.userName = userName; this.password = password; } public void handle (Callback[ ] callbacks) throws UnsupportedCallbackException { for (int i = 0; i < callbacks.length; ++i) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback) callbacks[i]; nc.setName(userName); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) callbacks[i]; pc.setPassword(password.toCharArray( )); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } } Once you get past this indirection, the rest of the JAAS API is straightforward. Figure C-1 shows the interactions in the API. Figure C-1. JAAS sequence diagramThe application instantiates a LoginContext with the application name and an application-specific CallbackHandler (in our case, we instantiate MyPassiveCallbackHandler with a username and password entered from the login form). The LoginContext reads the LoginModule Configuration file and instantiates the LoginModule(s). The application then calls LoginContext's login( ) method, which in turn calls the login( ) method of each LoginModule. MyPassiveCallbackHandler returns the NameCallback (with the username) and PasswordCalback to each LoginModule when it calls MyPassiveCallbackHandler's handle( ) method. C.1.6. JAAS LoginModule Configuration and DeploymentThe JAAS LoginModule Configuration file configures the LoginModule(s) used by a J2SE application, specifies their runtime behavior, and optionally provides them with initialization parameters. The template in Example C-2 shows the format of a LoginModule Configuration file. Example C-2. LoginModule Configuration fileApplication1 { ModuleClassInvokedFirst Flag ModuleOption1=value1 ... ModuleOptionN=valueN ; ModuleClassInvokedLast Flag ModuleOption1=value1 ... ModuleOptionN=valueN ; }; ... ApplicationN { ... }; The LoginContext invokes the LoginModules in the order declared in the Configuration file. The Module Options are initialization parameters (with values) for each LoginModule. C.1.7. LoginModule Configuration FlagsThe Flag in the LoginModule Configuration file serves two purposes:
Here are the options available for LoginModule Configuration Flags:
Although JAAS provides a sophisticated set of options, we're going to be conservative and set our LoginModule(s) to Required because we don't want to allow the user to access sensitive portions of an application unless they successfully log on to all the security realms. When filled in with real LoginModules and settings, the above LoginModule Configuration file template works in a J2SE environment when you add it your application's CLASSPATH. We use a J2SE-style LoginModule Configuration file when we create an external application client, but this won't work with most J2EE application servers. Refer to the Security chapter to see how to configure a server-side LoginModule on JBoss. |