The WebSphere® Application Server security framework heavily uses JAAS. It provides two custom extension points: application login configurations and system login configurations.
One application login configuration consists of a series of JAAS LoginModules and is intended for application programmatic authentication that use JAAS. In WebSphere Application Server, some default application login configurations are predefined, such as WSLogin and ClientContainer. It is actually WSLoginModuleImpl that performs the work for these predefined application logins. This LoginModule supports both username/password and credential token authentication mechanisms. (For the credential token authentication mechanism, the token must be one recognized by WebSphere Application Server, such as an LTPA token.) A stand-alone Java™ client, client container applications, servlets, JSP files, and EJBs can use this LoginModule to perform a programmatic login.
WebSphere system login configurations are primarily used by the WebSphere Security Runtime. WebSphere Application Server also provides several predefined system login configurations such as RMI_INBOUND, RMI_OUTBOUND, and WEB_INBOUND. The LoginModules within these login configurations are dynamically invoked by Security Runtime. For example, when an HTTP request comes in, the LTPALoginModule and WsMapDefaultInboundLoginModule that are in WEB_INBOUND system login configuration are called to fulfill the authentication request, if configured to do so. Stacking one or more custom LoginModules into predefined system login configurations can extend system logins.
WS-EAF falls into the category of application logins. A new application login configuration is created called FileNetP8Engine. By default, it uses WSLoginModuleImpl to handle username/password authentication mechanism. To use WS-EAF for supporting custom binary security token, you must implement a new LoginModule and add it into the FileNetP8Engine application login configuration. Furthermore, in the WebSphere environment, a custom LoginModule cannot instantiate a WSCredential, which is stored inside a valid JAAS Subject after successful authentication, so another WebSphere-provided LoginModule must be stacked to handle creation of WSCredentials.
Value: a custom implementation of java.security.Principal
<entries xmi:id="JAASConfigurationEntry_FileNetP8Engine" alias="FileNetP8Engine">
<loginModules xmi:id="JAASLoginModule_1"
moduleClassName="com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy" authenticationStrategy="SUFFICIENT">
<options xmi:id="Property_2" name="delegate" value="com.ibm.ws.security.common.auth.module.WSLoginModuleImpl"/>
<options xmi:id="Property_3" name="use_realm_callback" value="false"/>
<options xmi:id="Property_4" name="use_appcontext_callback" value="false"/>
</loginModules>
<loginModules xmi:id="JAASLoginModule_2" moduleClassName="com.filenet.authentication.MySampleLoginModule"
authenticationStrategy="OPTIONAL">
<options xmi:id="Property_11" name="debug" value="true" required="false"/>
</loginModules>
<loginModules xmi:id="JAASLoginModule_3"
moduleClassName="com.ibm.wsspi.security.common.auth.module.IdentityAssertionLoginModule"
authenticationStrategy="REQUIRED">
<options xmi:id="Property_21" name="debug" value="true" required="false"/>
</loginModules>
</entries>
You can modify this configuration entry from the WebSphere administration console. The order is important: the custom LoginModule MySampleLoginModule must precede IdentityAssertionLoginModule. Also, notice in the previous stanza that WSLoginModuleImpl is configured and has the Sufficient flag set to provide the default username/password authentication mechanism.
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
//This callbackHandler is the one passed by WS-EAF when the authentication process begins.
this.callbackHandler = callbackHandler;
this.subject = subject;
this.sharedState = sharedState;
}
public boolean login()
{
Callback[] callbacks = null;
callbacks = new Callback[1];
callbacks[0] = new TextInputCallback("WSIHEADER");
callbackHandler.handle(callbacks);
String wsiHeader = ((TextInputCallback)callbacks[0]).getText();
Parse wsiHeader and retrieve the BinarySecurityToken, ValueType.
Custom authentication using the BinarySecurityToken.
final String username = Retrieve the username information
//Prepare the trust map.
Map trustMap = new HashMap();
trustMap.put("com.ibm.wsspi.security.common.auth.module.IdentityAssertionLoginModule.trusted",
new Boolean(isValidUser));
//Create custom principal.
Principal prin = new Principal(){
public String getName(){
Return username;
}
};
trustMap.put("com.ibm.wsspi.security.common.auth.module.IdentityAssertionLoginModule.principal", prin);
//Now put the trustMap into shared state.
sharedState.put("com.ibm.wsspi.security.common.auth.module.IdentityAssertionLoginModule.state", trustMap);
}
The callback handler that is used in the login method is the one passed in from WS-EAF, and we are using the WSIHEADER prompt to retrieve the entire WS-Security header. Notice how the trusted map is constructed after authentication/validation. An anonymous java.security.Principal implementation is used for the custom Principal. The IdentityAssertionLoginModule retrieves the trusted map from the loginContext shared state after the custom login method completes.