J2EE provides a rich set of security-related functions for authentication, authorization, attribution, and access control through the Java Naming and Directory Interface (JNDI) and Java Authentication and Authorization Service (JAAS).
The Java security model provides policy-based access controls for Java applications. This security model provides protection based on the physical origin of the classes in use as well as identity services supported by their digital signature. The Java Authentication and Authorization Service APIs further extend the Java security model by allowing an application at runtime to take into account a user's identity. These APIs make a powerful combination for custom authentication and authorization in your Web service.
The Java Authentication and Authorization Service allows pluggable authentication (Figure 15.7) into an application, using several techniques. First, the authentication interfaces hide the complexity of the actual authentication mechanisms. Applications using this approach will not need to know nor care about what authentication protocol is in use. Second, JAAS allows authentication protocols to be stacked. In your Web service, you may require multiple authentication mechanisms be used before identity is established. As an example, accessing a payroll Web service may require a Kerberos login and a SQL server login. JAAS
comes with sample authentication modules for Java Naming and Directory Interface (JNDI), Unix (NIS), Windows NT (Domains), Kerberos, and Keystore.
Using Java Authentication and Authorization Service within a Web service is simple to implement but subtly different from normal Java security. Unlike Java security, authentication is not associated with the instantiation of a class or invocation of an instance method. When using JAAS, an application wishing to authenticate a user constructs a javax.security.auth.LoginContext and calls its login() method. When the application no longer requires the authenticated identity, it calls the LoginContext's logout() method.
You may have noted that neither login() nor logout() takes any arguments. This was done for ease of use. The LoginContext constructor does require parameters, however. The first parameter is the JAAS configuration file name. The configuration file contains the appropriate JAAS LoginModule(s), to authenticate the current user.
Let us look at simple configuration file:
// JAAS Security Policy record grant Codebase "www.flutebank.com", Signedby "peanut" { Principal com.flutebank.Principal "pamela" { FilePermission "/web/service/-", "read"; } // Login module configuration record InternalLogin { internal.TrustedLoginModule required debug=true; } ExternalLogin { internal.TrustedLoginModule required; com.sun.security.auth.module.NTLoginModule sufficient; com.chiltown.Kerberos optional debug=true; };
The above configuration file indicates that an attempt by InternalLogin to authenticate a subject will be successful only if the TrustedLoginModule succeeds. Likewise, if the ExternalLogin tries to validate a subject, it can use other authentication providers. A Web services provider may implement code similar to the following:
import java.security.*; import javax.security.auth.*; // Create a new login context LoginContext ctx = new LoginContext("ContextName", CallbackHandler); // Authenticate the subject ctx.login(); // Get the subject Subject sub = ctx.getSubject(); // Enforce Access Controls Subject.doAs(sub, action);
JAAS APIs supports a wide variety of pluggable authentication modules (PAM). In some authentication scenarios, authentication could consist of specifying a username and password. In other scenarios, the service may require name and a fingerprint, retinal scan and distinguished name, digital certificates and voice recognition, or some authentication mechanism that hasn't yet been invented.
The login() takes no methods. The approach used to get credentials to an authentication provider is to call the initialize() method of each LoginModule and pass in zero to n of javax.security.auth.callback.CallbackHandler. As an example, if you wanted to authenticate a user based on username and password, the LoginModule would examine the Callback array and look for instances of javax.security.auth.callback.NameCallback and javax.security.auth.call-back.PasswordCallback. The LoginModule can then authenticate the user appropriately.
The common classes shared by both JAAS authentication and authorization are located in javax.security.auth.Subject, which contains information for an entity such as principals and public and private credentials. The interface java .security.Principal represents a principal. A Web service may need to authorize access to a particular resource but must first authenticate the source of the request. The term subject represents the source of the request. Once authenticated, the subject is populated with associated identities.
A person named Daisy who uses your service may have a name principal ("Daisy Burney") and an SSN principal ("987-00-123") that distinguishes her from other subjects. Subjects may own security-related attributes, known as credentials. Sensitive credentials that require special protection are stored with a private credential set. These types of credentials are usually private cryptographic keys. Credentials such as digital certificates are stored in a public credential set.