Understanding WAM JAAS Login Modules
A LoginModule is concerned with authentication, the mechanism by which callers prove that they are acting on behalf of specific users or systems.
You use JAAS to establish trust by validating a user’s Credentials (often a username and password) through creation of of a LoginContext. (see Figure 1).
After successfully proving a caller’s identity, a LoginContext is saved in a WAM session object, which allows an identified user or system to be authenticated to other entities.
Figure 1 - The WAM JAAS authentication flow
To create a new LoginModule, you implement the LoginModule interface. A Configuration specifies the LoginModules you will use with WAM. Because LoginModules are pluggable, you can implement them without modification to WAM. Because they are stackable, you can specify how authentication to one or more LoginModules is required to access any resource.
A resource is any entity you want to secure against unauthorized access. The level of granularity is up to you. For example, you can consider a resource to be: single web page or a collection of pages; a web application; an Enterprise JavaBean (EJB) within a web application; or a method within a EJB.
The LoginContext reads the configuration and instantiates the specified LoginModules. Each LoginModule is initialized with a Subject, a CallbackHandler, shared LoginModule state, and LoginModule-specific options.
A Subject is the container that holds authentication information about the user or service being authenticated, including relevant Principals and Credentials (see Figure 2). A Principal is any entity such as an individual user, a login id, or groups to which a user belongs. A user usually represents a person. A group is a category of users, classified by common traits to facilitate administration.
Figure 2 - Joe is authenticated and belongs to groups Admin and Employee, the associated Principals and Joe’s digital certificate are saved in the Subject.
In the initialize method, the WAM LoginContext sends a Subject, a CallbackHandler,
shared state, and options to the LoginModules. LoginModules use the CallbackHandler
to communicate with users, often to prompt for usernames and passwords. Other
Credentials may be required such as digital certificates, in which case the
CallbackHandler may be null. LoginModules may also share state information,
or define specific configuration values to control behavior. Options are defined
using a key-value syntax, such as
debug=true. The LoginModule
stores the options as a Map
so that the values may be retrieved using the key.
In addition to standard JAAS initialization, LoginModules used within WAM can also be initialized with a security domain-specific Logger and ServiceFinder. These objects enable a LoginModule to log messages to the security domain-specific trace log file and to find WAM Services hosted within the enclosing security domain. Specific examples will be shown in sections: Getting a WAM Logger, and Getting a WAM ServiceFinder.
After initialization, the WAM LoginContext invokes the LoginModule’s login method. Here, you write the code that will invoke the CallbackHandler (if required) and authenticate the user-supplied Credentials against your repository. The login method performs the authentication and saves the result as private state information. The login method returns one of the following:
true, if it succeeds.
false, if it should be ignored.
A LoginException or a subclass of LoginException, if there was a failure.
If a failure occurs, you must not retry or introduce delays. The responsibility of such tasks belongs to WAM. If WAM is configured to retry authentication (three times, for example), each relevant LoginModule’s login method will be called again up to the limit.
See Configuration for more information on how to modify the values that control behavior as authentication proceeds down the stack.
If the LoginContext’s overall authentication succeeds, then the commit method for each relevant LoginModule is invoked. The commit method checks its privately saved state to see if its own authentication succeeded. If the overall LoginContext authentication succeeded and the LoginModule’s own authentication succeeded, then the commit method associates the relevant user Principals and Credentials with the Subject.
The abort method is invoked to clean up the state when the LoginModule’s login or commit method fails, or the LoginContext’s overall authentication fails. In each case, the LoginModule may have different requirements to remove saved authentication state.
The logout method performs the logout procedures, such as removing Principals or Credentials from the Subject, or logging session information.
If you are familiar with UML sequence diagrams, Figure 3 shows a sequence diagram of the method invocation sequence for the WAM authentication service and relevant objects.
Figure 3 - Sequence diagram of WAM authentication flow
Authentication using the JAAS classes and the WAM authentication service is performed in the following manner:
WAM initiates the authentication process by instantiating a LoginContext object. The LoginContext consults a Configuration to load the configured LoginModules.
The LoginContext object initializes all the LoginModules configured for the relevant security domain.
WAM invokes the LoginContext’s
login()method, which calls the initialize method of each configured LoginModules.
The LoginModule’s login method is invoked for each configured LoginModule.
If login is successful, the commit method of the relevant LoginModules is invoked to associate the Principals and Credentials with the LoginContext’s Subject.
The WAM authentication service saves the LoginContext with its populated Subject in the Session object.
LoginModules must throw a LoginException through the
logout() methods to indicate a failed request. This may serve not only to
indicate that the request failed, but why the request failed. For example, a
LoginModule might throw a LoginException for any of these reasons:
Runtime failure, like the inability to connect with a remote user directory.
Missing or invalid authentication credentials, like username and/or password.
User account has expired.
User credential has expired.
User has previously attempted to login and failed a certain number of times within a given period.
A LoginModule may throw any subclass of
javax.security.auth.login.LoginException from its
logout() methods. A subset of the following standard LoginException classes are used by typical LoginModule implementations.
javax.security.auth.login.LoginException: Used to indicate a error while trying to authenticate a user. In general, this Exception is thrown by LoginModule implementations to indicate a configuration, connectivity, or runtime error, not a "normal authentication failure".
javax.security.auth.login.FailedLoginException: Used to indicate a authentication failure. For example, a user may not exist, the supplied password may be invalid.
javax.security.auth.login.AccountExpiredException: Used by LoginModules when they determine that an account has expired. For example, a LoginModule, after successfully authenticating a user, may determine that the user’s account has expired. In this case the LoginModule throws this exception to notify the application. The application can then take the appropriate steps to notify the user.
javax.security.auth.login.CredentialExpiredException: Used by LoginModules when they determine that a Credential has expired. For example, a LoginModule authenticating a user in its login method may determine that the user’s password, although entered correctly, has expired. In this case the LoginModule throws this exception to notify the application. The application can then take the appropriate steps to assist the user in updating the password.
In addition, you are free to create new LoginException subclasses to convey appropriate context for a failed authentication request.
NOTE: WAM provides a way for each security domain
to define standard, customized LoginException messages based on the class or
subclass of the LoginException that may be thrown by a LoginModule. Standard
LoginException messages are provided in a file named
in each security domain’s home directory. For more information, see the WAM
Administrator’s Guide, section: Customizing
WAM Authentication Pipeline
This diagram describes how authentication requests are handled by the WAM authentication pipeline.
When the WAM server receives an authentication request via its authentication protocol, the Authentication service:
Looks up the
CallbackHandlerclass registered for the application-specific
Instantiates a JAAS
LoginContext, giving it the
LoginContextto attempt authentication using the information provided in the authentication request.