Introduction

This document describes how to use the FileNet® P8 Content Engine Web Service Extensible Authentication Framework (WS-EAF). The information in this document is intended for developers who want to extend the functionality of WS-EAF by developing custom login modules that will handle binary security tokens as defined in WS-Security standards. To derive full benefit from the information in this document, we assume the reader is familiar with the WS-Security standard as well as the Java™ Authentication and Authorization Service (JAAS) standard. Sections provided in this document include:

Overview

The Content Engine server accepts incoming requests over two transport protocols: an Enterprise Java Bean (EJB) transport and a web service transport. Authentication over the EJB transport is extensible through use of the JAAS standard. The Java 2 Enterprise Edition (J2EE) application server authenticates callers before they can access the EJB. Extensible authentication over the EJB transport is not discussed further in this document because it is defined by the JAAS industry standard.

WS-EAF provides a pluggable authentication mechanism for the web service transport. The authentication mechanism in WS-EAF is based on the Web Service Security (WS-Security) OASIS standard and implemented with the JAAS standard.

The WS-Security standard defines how security credentials are formatted and inserted in a web service request. When a web service request arrives in the Content Engine server, the Content Engine web service listener extracts the WS-Security header and performs a JAAS login based on its contents. If this JAAS login is successful, then the web service listener passes the request to the Content Engine EJB layer within the EJB container.

The Content Engine web service provides out-of-the-box-support for the WS-Security Username Token profile, as well as the Kerberos profile. Support for other WS-Security compliant approaches can be added through the WS-EAF. (See Resources for links to information about the WS-Security standard and JAAS).

In general, to extend Content Engine web services authentication, you must write a custom LoginModule and plug it into WS-EAF. Depending on the targeted application server and actual authentication mechanism, the process could be very complex and requires a thorough understanding of the authentication framework of different application servers.

WS-EAF supports both Java and .NET web service clients when using the web service transport in the Content Engine server. Java clients include standalone Java applications, servlets, and Java™Server Pages (JSP). There are many tools available to aid in writing Java-based web service applications. You can program a Java web service client using Java™ API for XML-based RPC (JAX-RPC), Java™ API for XML Messaging (JAXM), or Apache's WSS4J.

In the .NET environment, Microsoft Web Services Enhancements (WSE) 3.0 is the recommended API for developing web service-based clients. See Resources for links to information sources for web service client development. To take advantage of WS-EAF, users of the Content Engine.NET API can also easily send requests to the Content Engine server using the custom token types.

WS-EAF

This topic briefly introduces JAAS and gives an overview of WS-EAF.

JAAS

WS-EAF makes heavy use of the JAAS programming model. JAAS is a standard Java framework to manage authentication and authorization tasks. JAAS is composed of an application programming interface (API) and a service programming interface (SPI). The figure below depicts a high-level representation of the JAAS authentication model:


Authentication occurs in the JAAS LoginModules. In addition to supporting the pluggable authentication model (PAM), LoginModules are also stackable. Stacking LoginModules allows for defining scenarios in which more than one step is required to complete successfully for authentication to succeed. For example, a configuration may require a username/password authentication, as well as a separate biometric authentication.

For more information on JAAS, see Resources.

WS-EAF Overview

By leveraging the JAAS authentication model, WS-EAF automatically supports a pluggable and stackable authentication mechanism. WS-EAF is a very generic authentication framework and doesn't expose any FileNet-specific SPI for use in extending its functionality. Instead, you typically use the standard JAAS API and an application server-specific SPI available from your application server vendor.

WS-EAF consists of a set of conventions for writing a JAAS LoginModule that is able to interact with the Content Engine web service listener to obtain the credentials that are present in the WS-Security header of an incoming request packet. The diagram below illustrates how this interaction occurs for the very first login process (descriptions of the numbered steps follow the diagram):

  1. A Content Engine web service client sends a request containing a custom set of credentials packaged in a WS-Security header.
  2. The request arrives at the Content Engine web service listener. The web service listener invokes the WS-EAF authentication mechanism. A JAAS CallbackHandler (CBH) is created by WS-EAF and seeded with the contents of the WS-Security header.
  3. A JAAS login is performed, specifying the "FileNetP8Engine" JAAS configuration, and the CallbackHandler created in the previous step.

    Note  The "FileNetP8Engine" stanza is the default JAAS configuration entry to WS-EAF. Because this is just another of the available JAAS key-value pairs of configuration parameters, you can define an alternative login stanza via the administration console using the JAASConfigurationName key. For the purposes of illustration, this document uses the default name when referencing the stanza in text and examples.

  4. The standard JAAS runtime looks up the login module(s) that are listed in the JAAS configuration file for the "FileNetP8Engine" stanza, and invokes each of the listed LoginModules, passing in the web service CallbackHandler as a parameter.
  5. The custom WS-EAF JAAS login module instantiates one or more standard JAAS callbacks and passes these callbacks to the handle() method of the CallbackHandler.For each callback that the client has requested, the web service CallbackHandler supplies the callback with requested XML fragments from the incoming WS-Security header, such that they can be retrieved by the custom WS-EAF JAAS LoginModule.
  6. The LoginModule is now in possession of the WS-Security header information, and is able to use this information to perform its proprietary authentication process. If the authentication is successful, then a JAAS Subject is populated and returned.
  7. The web service listener now has a valid JAAS Subject, and can call the Content Engine service to handle the request, via the Content Engine EJB.

To improve performance, WS-EAF caches the authenticated Subject upon a successful JAAS login. The cache key is an encoded form of a username/password combination or a binary security token. The cache is configurable through the FileNet Enterprise Manager administration tool. If another SOAP request is sent to the web service listener with the same credentials, the WS-EAF retrieves the Subject directly from local cache without performing another JAAS login, provided that the cache entry is still valid (that is, not timed-out or purged).

Extending WS-EAF involves the following tasks:

Inside a custom LoginModule, the following standard JAAS callbacks are supported:

NameCallback and PasswordCallback are used for Username/Password token authentication mechanisms. Since the Content Engine server supports username/password authentication out-of-the-box, developers creating custom solutions should use the TextInputCallback for handling custom binary security. You can instantiate one or more TextInputCallback(s), passing in different string prompts for each. Depending on the prompt passed in, WS-EAF sets appropriate values to the instance of TextInputCallback and corresponding credential information can be retrieved using TextInputCallback.getText() inside a custom LoginModule. The supported prompts and the values returned by the getText() method are listed below:

If you are using WS-EAF and want to retrieve the WS-Security header XML string from within your custom login module, you must specify the following JVM argument for the Content Engine Server: -Dcom.filenet.authentication.wsi.needsWSIHeader. (Note that you can also add it as an entry to the FileNet.properties file.) This property controls whether the WS-Security header XML string is generated for each WSI request, which has a performance cost. So for customers who do not use WS-EAF, there is no need to specify this JVM property. This property is also not needed if you use WS-EAF but do not wish to retrieve the WS-Security header XML string from within your custom login module.

The example below illustrates usage of TextInputCallback and the prompt parameter. Suppose the user designed a custom binary security token for use with the Content Engine 4.0 web service transport. When the Content Engine web service listener receives the SOAP call, the WS-Security header might look like this:

<wsse:Security soap:mustUnderstand="1">
      <wsse:BinarySecurityToken ValueType="binary"
      EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
      xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
      wsu:Id="SecurityToken-f6da72f4-df43-4765-adb7-86eb583e7419">
            RGFwaG5lVGVzdHxmaWxlbmV0MTIz
      </wsse:BinarySecurityToken>
</wsse:Security>

Notice the BinarySecurityToken block, which represents the custom binary security token. After WS-EAF initiates the JAAS authentication process, the custom authentication credential can be retrieved by a custom LoginModule with the following code snippet:

javax.security.auth.callback.Callback[] callbacks = new Callback[2];
callbacks[0] = new TextInputCallback("BINARYTOKEN");
callbacks[1] = new TextInputCallback("BINARYTOKEN_VALUETYPE");
callbackhandler.handle(callbacks);

//retrieve the binary security token
String binaryToken = ((TextInputCallback)callback[0]).getText();
//retrieve the binary security token value type
String valueType = ((TextInputCallback)callback[1]).getText();

Had the TextInputCallback been constructed with the "WSIHEADER" prompt, the getText() method would return the entire WS-Security header as an XML String. The custom LoginModule can parse this XML String to locate the credential.

By using TextInputCallback, WS-EAF provides sufficient knowledge for a custom LoginModule to authenticate the SOAP request.

Developing custom LoginModules for different application servers can become complicated. Using WS-EAF describes some of the issues related to using WS-EAF in different J2EE application server environments supported by the Content Engine.

Using WS-EAF

Each J2EE application server has integrated JAAS into their security framework, but since the J2EE standard says little about exactly how to do this, each J2EE vendor has its own integration approach. This means that each J2EE application server has a special, unique way of doing a "valid" login, which is defined here as a JAAS login that will be recognized by the rest of the vendor's J2EE framework. Not performing a JAAS login the "valid" way for that application server will not work correctly in one way or another and, will not propagate the security identity to the FileNet P8 EJB layer.

As an example, in BEA WebLogic®, the JAAS Subject has special "validated" principals that, by default, are digitally signed only by a WebLogic Authentication Provider, whereas IBM® WebSphere® has taken the approach of adding special WSPrincipals and WSCredentials objects that can only be generated by special WebSphere LoginModules.

JBoss does not use special, valid Subjects, but employs the strategy of using "hidden" thread local storage to store and pass around security data. This "thread identity" should be setup only by a JBoss login module.

The following subtopics provide more information that is specific to supported application servers.

WebLogic

WebLogic has a security framework that uses Security Providers. There are a variety of these providers for special jobs, such as Role Mapping Providers or Authorization Providers, but for WS-EAF, we are only interested in Authentication Providers.

An Authentication Provider is a Java™ Management Extensions (JMX) managed bean (Mbean) that has a UI page or two in the WebLogic administration console for setting various login options. Each Authentication Provider has a flag—OPTIONAL, REQUIRED, REQUISITE, or SUFFICIENT—just as does a JAAS LoginModule. They can even be "stacked" in WebLogic security realms in much the same way that LoginModules can be stacked in a JAAS configuration stanza.

An Authentication Provider has an associated JAAS LoginModule, which performs the JAAS login. The rest of the Authentication Provider provides a framework that automatically digitally signs Principals created by its LoginModule and also has methods that validate such Principals later and that perform such tasks as identity assertion.

Implementing the Custom LoginModule

The WebLogic security framework can be divided into a WebLogic client side API and server side SPI. The client side API provides interfaces for applications to perform programmatic authentication or implement custom JAAS LoginModules. On the server side WebLogic provides a Security Service Programming Interface (SSPI), which can be used to implement custom security providers. Viewed from the WebLogic application standpoint, WS-EAF is considered an in-container application client.

WebLogic application server supplies a default UsernamePasswordLoginModule for general client authentication with username/password credentials. For other authentication mechanisms, you will typically need to implement your own client LoginModule. The WebLogic API provides three important methods that are useful in developing a custom LoginModule for WS-EAF:

Either a thick client or an in-container client such as a servlet can invoke a LoginModule implemented with Authenticate.authenticate method. The method takes an Environment argument. This Environment map must contain a username and a credential string. The authenticate method calls into the WebLogic server side security runtime, where the work is done by WebLogic security providers. The WebLogic security providers perform the actual authentication and return a signed valid Subject to the client application.

From the above description of the Authenticate.authenticate() method, you can see that for a typical extensible authentication implementation using WS-EAF, it may be of little use, as it depends on an underlying username/password authentication mechanism. However, if the custom binary security token can be decomposed into a username/password pair, and the decomposed username/password information is intended to be used in the authentication process, then a LoginModule implemented with Authenticate.authenticate will be the simplest way to achieve the goal.

In most other use cases, you should use one of the above Authentication.login methods to implement your custom LoginModule (referred to as an "application LoginModule").

The following pseudo-code shows what a typical custom application LoginModule needs to do in the initialize(), login() and commit() methods:

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
      this.callbackHandler = callbackHandler;
      this.subjectBeforeCommit = null;
      this.subject = subject;
}

public boolean login()
{
      subjectBeforeCommit = Authentication.login(callbackHandler);
}

public boolean commit()
{
      subject.getPrincipals().addAll(subjectBeforeCommit.getPrincipals());
      subject.getPublicCredentials().addAll(
      subjectBeforeCommit.getPublicCredentials());
      subject.getPrivateCredentials().addAll(
      subjectBeforeCommit.getPrivateCredentials());
}

The callbackHandler in the above example is the one WS-EAF creates when it initiates a standard JAAS authentication process. Notice how Authentication.login is called and the returned Subject is saved in the login() method. Inside the commit() method, the Principals/credentials are transferred to the current authenticating Subject.

The Authentication.login() method calls into the WebLogic security framework and eventually invokes the custom Authentication Provider's LoginModule implementation.

Implementing a Custom Authentication Provider

A WebLogic Authentication Provider is a JMX MBean that can be deployed from the WebLogic administration console. The WebLogic security framework also uses JAAS internally so implementing a custom Authentication Provider involves a JAAS LoginModule implementation (referred to as the Security Provider LoginModule), as well as implementing some additional SPI interfaces that allow the custom Authentication Provider to interact with the application server. The LoginModule is the central place in which authentication occurs. So here the focus is on the LoginModule component implementation. (See Resources for links to information about the actual steps in the implementation and deployment of the custom Authentication Provider.)

The pseudo-code below shows what needs to be done inside the key methods for the Authentication Provider LoginModule:

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
      //This callbackHandler is the one passed by authentication.login() method
      this.callbackHandler = callbackHandler;
      this.subject = subject;
      this. principalsForSubject = new Vector();
}

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
      Retrieve the user and group information after authentication
      principalsForSubject.add(new WLSUserImpl(username));
      principalsForSubject.add(new WLSGroupImpl(groupName));
}

public boolean commit()
{
      subject.getPrincipals().addAll(principalsForSubject);
}

Notice inside the login() method, the callbackHandler is the one passed by Authentication.login() method, and this example uses the "WSIHEADER" prompt to retrieve the whole WS-Security header. After the Authentication Provider finishes authentication, the Subject is passed to the WebLogic Principal Validator to sign, thereby making it valid.

Additional Notes:

  1. The Principals created by the LoginModule must be derived from WLSPrincipal or must use the supplied WLSUserImpl or WLSGroupImpl classes so that the default PrincipalValidatorImpl works with them. You can avoid this, but at the price of implementing your own PrincipalValidator class.
  2. WebLogic makes a distinction between privileged users and non-privileged users. A privileged user has at least one group Principal, while a non-privileged user has none. If non-privileged, then WebLogic uses the default JVM user, which is the first user who logged on for that JVM. Refer to Programming WebLogic JNDI on the BEA web site (http://e-docs.bea.com/wls/docs81/jndi/jndi.html) for work-arounds for this problem with JNDI contexts and the runAs command.
  3. WebLogic adds an extra LoginModule option, IdentityAssertion, which must be handled by any custom LoginModule. When true, the module should ask for a NameCallback only (no PasswordCallback) and should only be validating that the name is a valid Principal at the moment.

WebSphere

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 using JAAS. In WebSphere, some default application login configurations are predefined, such as WSLogin, ClientContainer, etc. The actual workhorse of these predefined application logins is WSLoginModuleImpl. This LoginModule supports both username/password and credential token authentication mechanisms. (Note that for the credential token authentication mechanism, the token has to be one recognized by WebSphere, such as an LTPA token.) A standalone 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 also provides several predefined system login configurations such as RMI_INBOUND, RMI_OUTBOUND, WEB_INBOUND etc. 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, since in the WebSphere environment, a custom LoginModule can't instantiate a WSCredential, which is stored inside a valid JAAS Subject after successful authentication, another WebSphere provided LoginModule has to be stacked to handle creation of WSCredentials.

In the next few paragraphs, we use the "Identity Assertion with Trust Validation" approach to develop a custom LoginModule and stack it with com.ibm.wsspi.security.common.auth.module.IdentityAssertionLoginModule in a WebSphere 6 application server environment. (For more information, see Resources for the "WebSphere Identity Assertion with Trust Validation" link). The overall authentication consists of two steps:

First let's show what the application login configuration looks like after stacking the custom LoginModule and IdentityAssertionLoginModule. The following is the "FileNetP8Engine" application login configuration entry excerpted from the WebSphere security.xml file:

<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 has to be in front of IdentityAssertionLoginModule. Also note in the above stanza, WSLoginModuleImpl is configured and has the "Sufficient" flag to provide the default username/password authentication mechanism.

Below is pseudo-code for the MySampleLoginModule example's initialize() and login() methods:

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{

//This callbackHandler is the one passed by WS-EAF when 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 used in the login method is the one passed in from WS-EAF, and we are using "WSIHEADER" prompt to retrieve the whole WS-Security header. Note 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 custom login() completes.

JBoss

The JBoss application server allows applications to be secured by declaring a security domain inside their deployment descriptor (jboss.xml or jboss-web.xml). The JBoss security component framework (JBossSX) is automatically invoked to perform security checks by intercepting EJB calls. JBossSX leverages the JAAS framework in its default implementation.

Whereas WebLogic and WebSphere return a valid JAAS Subject after a successful JAAS login, JBoss takes a different approach. Using JBoss terminology, a "client login" is a login from either a standalone Java client or an in-container servlet. In JBoss, upon a successful programmatic application JAAS client login, the returned Subject is not a "valid" one and cannot be reused by a different thread. In the JBoss model, client logins just capture the caller's credentials and associate them with the current thread. The actual authentication is deferred until an attempt is made to access a server resource (for example, an EJB). When a server resource is accessed, the credentials that were associated with the thread by the client LoginModule are used by the server LoginModule to perform the real authentication.

To associate the caller's credentials with the current calling thread, JBoss uses two built-in LoginModules: ClientLoginModule and AltClientLoginModule. When these two LoginModules are used standalone, they retrieve the username and credentials from the JAAS NameCallback and PasswordCallback, respectively. By setting the module option "password-stacking" to true, they instead retrieve the username and password credential from the JAAS shared state map, which can be set by other stacked LoginModules. The major difference between ClientLoginModule and AltClientLoginModule is that the latter delays the association of caller identity to the current thread until the JAAS commit phase.

The Content Engine EJBs are secured under a security domain named "FileNet", while application logins are configured using the "FileNetP8Engine" JAAS stanza in the JBoss login-config.xml file.

The following example JAAS stanzas illustrate typical setups for supporting custom binary security tokens:

FileNetP8Engine {

   com.foo.UserNamePasswordLoginModule optional;
   com.foo.ClienSecurityTokenLoginModule optional;
   org.jboss.security.ClientLoginModule required
    multi-threaded=true password-stacking=useFirstPass

}

FileNet{
          org.jboss.security.auth.spi.LdapLoginModule sufficient;
          com.foo.ServerSecurityTokenLoginModule sufficient;
}

Note that in the above JAAS configuration stanza, we simultaneously support two authentication mechanisms: username/password-based authentication, and custom security token authentication. From the above configurations, you can see that you must implement two LoginModules to support custom binary security tokens:

The following paragraphs describe the WS-EAF implementation of these two LoginModules.

Implementing ClientSecurityTokenLoginModule

The purpose of ClientSecurityTokenLoginModule is not to perform an actual authentication, but to set up the credential information for the stacked org.jboss.security.ClientLoginModule to pick up. ClientLoginModule, when configured with the "password-stacking=useFirstPass" option, retrieves authentication credential values from the JAAS shared state map by looking up two predefined keys and then associating this credential information with the current calling thread as discussed earlier. The two keys are:

The following pseudo-code highlights what the login() method should do in ClientSecurityTokenLoginModule to set up these two keys:

public boolean login() throws LoginException

{

Callback callbacks[] = new Callback[1];
//callback used to retrieve wsi security header.
callbacks[0] = new TextInputCallback("WSIHEADER");
String wsiHeader = ((TextInputCallback)callbacks[0]).getText();
// set up the shared state
sharedState.put("javax.security.auth.login.name","anything");
//the stacked ClientLoginModule will retrieve this as credential
sharedState.put("javax.security.auth.login.password", wsiHeader);

return true;

}

Since we are passing the whole WS-Security header to JBossSX, we only use the password key and just put arbitrary data as the value of the name key. It is also safe to not set anything into the name in this case. You can also set the name key to a username and the password key to a password in cases where your binary security token can be decomposed to retrieve username and password values.

Implementing ServerSecurityTokenLoginModule

The JBossSX SPI provides some abstract LoginModules to facilitate the development of a custom LoginModule. Since this minimizes the development effort and enforces correct implementation of the JBoss Subject usage patterns (see JBoss reference information), it is recommended that a custom LoginModule extend org.jboss.security.auth.spi.AbstractServerLoginModule for WS-EAF development. The following pseudo-code shows the key details of this approach:

public class FnDemoServerBinaryTokenLoginModule extends
    AbstractServerLoginModule {

private Principal identity;

public boolean login() throws LoginException {
super.loginOk = false;
Callback callbacks[] = new Callback[1];

//callback used to retrieve wsi security header.
callbacks[0] = new PasswordCallback("pass", false);
super.callbackHandler.handle(callbacks);
String wsiHeader =
     new String(((PasswordCallback)callbacks[0]).getPassword());
Parse the wsi security header and extract credentials.
Do actual authentication here and find out the username
//authentication passed. set up JBoss identity.
if (identity == null) {
     identity = super.createIdentity(username);
}

super.loginOk = true;
return super.loginOk;

}

protected Principal getIdentity() {
     return identity;
}

protected Group[] getRoleSets() throws LoginException {

//set up the caller principal as current user.
Group[] groups = {new SimpleGroup("CallerPrincipal")};
groups[0].addMember(identity);
return groups;

}

Inside the login() method, the WS-Security header is retrieved using PasswordCallback. The getIdentity() and getRolesSets() methods are template methods of AbstractServerLoginModule. They should be implemented to provide the caller's primary identity and group information. Since the Content Engine doesn't use role-based J2EE security, here we just set up the "CallerPrincipal" group, which provides the application identity rather than the security domain identity.

For more information on the JBoss security framework and the JBossSX SPI, see Resources.

Code Samples

Code samples are available for download on the IBM support page. (http://www.ibm.com/software/data/support).

Samples are available for WebLogic, WebSphere, and JBoss application server environments. A "readme" document included with the code samples explains how to use them.

Resources