JBoss.org Community Documentation
Authentication of a subject requires a JAAS login. The login procedure consists of the following steps:
An application instantiates a LoginContext
and passes in the name of the login configuration and a CallbackHandler
to populate the Callback
objects, as required by the configuration LoginModule
s.
The LoginContext
consults a Configuration
to load all the LoginModules
included in the named login configuration. If no such named configuration exists the other
configuration is used as a default.
The application invokes the LoginContext.login
method.
The login method invokes all the loaded LoginModule
s. As each LoginModule
attempts to authenticate the subject, it invokes the handle method on the associated CallbackHandler
to obtain the information required for the authentication process. The required information is passed to the handle method in the form of an array of Callback
objects. Upon success, the LoginModule
s associate relevant principals and credentials with the subject.
The LoginContext
returns the authentication status to the application. Success is represented by a return from the login method. Failure is represented through a LoginException being thrown by the login method.
If authentication succeeds, the application retrieves the authenticated subject using the LoginContext.getSubject
method.
After the scope of the subject authentication is complete, all principals and related information associated with the subject by the login method can be removed by invoking the LoginContext.logout
method.
The LoginContext
class provides the basic methods for authenticating subjects and offers a way to develop an application that is independent of the underlying authentication technology. The LoginContext
consults a Configuration
to determine the authentication services configured for a particular application. LoginModule
classes represent the authentication services. Therefore, you can plug different login modules into an application without changing the application itself. The following code shows the steps required by an application to authenticate a subject.
CallbackHandler handler = new MyHandler(); LoginContext lc = new LoginContext("some-config", handler); try { lc.login(); Subject subject = lc.getSubject(); } catch(LoginException e) { System.out.println("authentication failed"); e.printStackTrace(); } // Perform work as authenticated Subject // ... // Scope of work complete, logout to remove authentication info try { lc.logout(); } catch(LoginException e) { System.out.println("logout failed"); e.printStackTrace(); } // A sample MyHandler class class MyHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, 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); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } }
Developers integrate with an authentication technology by creating an implementation of the LoginModule
interface. This allows an administrator to plug different authentication technologies into an application. You can chain together multiple LoginModule
s to allow for more than one authentication technology to participate in the authentication process. For example, one LoginModule
may perform username/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators.
The life cycle of a LoginModule
is driven by the LoginContext
object against which the client creates and issues the login method. The process consists of two phases. The steps of the process are as follows:
The LoginContext
creates each configured LoginModule
using its public no-arg constructor.
Each LoginModule
is initialized with a call to its initialize method. The Subject
argument is guaranteed to be non-null. The signature of the initialize method is: public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
.
The login
method is called to start the authentication process. For example, a method implementation might prompt the user for a username and password and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices, or simply extract user information from the underlying operating system. The validation of user identity by each LoginModule
is considered phase 1 of JAAS authentication. The signature of the login
method is boolean login() throws LoginException
. A LoginException
indicates failure. A return value of true indicates that the method succeeded, whereas a return valueof false indicates that the login module should be ignored.
If the LoginContext
's overall authentication succeeds, commit
is invoked on each LoginModule
. If phase 1 succeeds for a LoginModule
, then the commit method continues with phase 2 and associates the relevant principals, public credentials, and/or private credentials with the subject. If phase 1 fails for a LoginModule
, then commit
removes any previously stored authentication state, such as usernames or passwords. The signature of the commit
method is: boolean commit() throws LoginException
. Failure to complete the commit phase is indicated by throwing a LoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
If the LoginContext
's overall authentication fails, then the abort
method is invoked on each LoginModule
. The abort
method removes or destroys any authentication state created by the login or initialize methods. The signature of the abort
method is boolean abort() throws LoginException
. Failure to complete the abort
phase is indicated by throwing a LoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
To remove the authentication state after a successful login, the application invokes logout
on the LoginContext
. This in turn results in a logout
method invocation on each LoginModule
. The logout
method removes the principals and credentials originally associated with the subject during the commit
operation. Credentials should be destroyed upon removal. The signature of the logout
method is: boolean logout() throws LoginException
. Failure to complete the logout process is indicated by throwing a LoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
When a LoginModule
must communicate with the user to obtain authentication information, it uses a CallbackHandler
object. Applications implement the CallbackHandler
interface and pass it to the LoginContext, which forwards it directly to the underlying login modules. Login modules use the CallbackHandler
both to gather input from users, such as a password or smart card PIN, and to supply information to users, such as status information. By allowing the application to specify the CallbackHandler
, underlying LoginModule
s remain independent from the different ways applications interact with users. For example, a CallbackHandler
's implementation for a GUI application might display a window to solicit user input. On the other hand, a callbackhandler
's implementation for a non-GUI environment, such as an application server, might simply obtain credential information by using an application server API. The callbackhandler
interface has one method to implement:
void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
The Callback
interface is the last authentication class we will look at. This is a tagging interface for which several default implementations are provided, including the NameCallback
and PasswordCallback
used in an earlier example. A LoginModule
uses a Callback
to request information required by the authentication mechanism. LoginModule
s pass an array of Callback
s directly to the CallbackHandler.handle
method during the authentication's login phase. If a callbackhandler
does not understand how to use a Callback
object passed into the handle method, it throws an UnsupportedCallbackException
to abort the login call.