Generating a dynamic LTPA token using a stacked JAAS login module

You can dynamically pass a username and password to the LTPA token generator, LTPAGenerateLoginModule, when using WSS SPIs. However, if you must use policy sets and bindings, you cannot do this in a standard configuration because both the callback handler, and the username and password in the callback handler are fixed values. You can use policy sets and bindings to create dynamic Kerberos tokens if a custom JAAS login module is used.

Before you begin

If you create a custom JAAS login module, or add a UsernameToken to the client's request context, you can customize the username and password that the LTPA token generator uses when creating an LTPA token. You can also customize the token by directly setting the token bytes that the LTPA token generator uses. Setting the token bytes is useful when an application developer wants to write code to obtain the LTPA token from the HTTP header of an inbound request and place it into the Security header of an outbound SOAP message.

About this task

The GenericSecurityTokenFactory provides SPIs that you can use to create a token that the LTPAGenerateLoginModule can use to customize the LTPA token that this module generates. These SPIs enable you to use dynamic usernames and passwords, or to directly set the token bytes, which are capabilities that the callback handler does not provide.

The following procedure shows how to use the stacked JAAS login module method to customize the username and password or token bytes. After you complete this procedure, you can also place the newly created token on the client's request context. For more information on how to place a token on the client's request context, refer to the following constants in com.ibm.wsspi.wssecurity.core.Constants Javadoc:

  • com.ibm.wsspi.wssecurity.token.tokenHolder
  • com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext

Procedure

  1. Create the dynamic token.

    Complete one of the following substeps.

    1. To customize the username and password, create a simple UsernameToken.
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
      ...
      GenericSecurityTokenFactory gstFactory = GenericSecurityTokenFactory.getInstance();
      UsernameToken myUnt = gstFactory.getSimpleUsernameToken("myUsername", "myPassword".toCharArray());
    2. To customize the token bytes, create a simple BinarySecurityToken
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.BinarySecurityToken;
      import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
      ...
      GenericSecurityTokenFactory gstFactory = GenericSecurityTokenFactory.getInstance();
      WSSUtilFactory utilFactory = WSSUtilFactory.getInstance();
      
      //callbackHandler is obtained from the initialize method in the Login Module
      Map reqHeaders = utilFactory.getHTTPRequestHeaders(callbackHandler);
      
      //getLtpaHeaderBytes is a method written by you to find the header that 
      //has the LTPA token in it in the header list, then return the encoded 
      //bytes out of the header.
      String encodedBytes = getLtpaHeaderBytes(reqHeaders); 
      
      byte [] decodedBytes = utilFactory.decode(encodedBytes);
      
      BinarySecurityToken bst = factory.getSimpleBinarySecurityToken(com.ibm.websphere.wssecurity.wssapi.token.LTPAv2Token, decodedBytes);
  2. Create a JAAS login module.
    package test.tokens;
    
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import java.util.Map;
    
    import javax.security.auth.Subject;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
    import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
    import com.ibm.websphere.wssecurity.wssapi.token.BinarySecurityToken;
    
    
    public class MyUntCustomLoginModule implements LoginModule {
      //For the sake of readability, this login module does not
      //protect against all NPE's
    
      private Map _sharedState;
      private Map _options;
      private CallbackHandler _handler;
    
      public void initialize(Subject subject, CallbackHandler callbackHandler,
                  Map<String, ?> sharedState, Map<String, ?> options) {
    
        this._handler = callbackHandler;
        this._sharedState = sharedState;
        this._options = options;  
      }
    
      public boolean login() throws LoginException {
    
        GenericSecurityTokenFactory factory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
    
        //code to create the BinarySecurityToken can be used
        //here instead of the simple UsernameToken
        UsernameToken unt = factory.getSimpleUsernameToken("myUsername", "myPassword".toCharArray());
    
        factory.putGeneratorTokenToSharedState(this._sharedState, unt);
    
        return true;
      }
      //implement the rest of the methods required by the
      //LoginModule interface
    }
  3. Create a new JAAS login configuration.
    1. In the administrative console, select Security->Global security.
    2. Under Authentication, select Java Authentication and Authorization Service.
    3. Select System logins.
    4. Create the generator with the custom module first.
      1. Click New, and then specify Alias = test.generate.ltpa.
      2. Click New, and then specifyModule class name = test.tokens.MyUntCustomLoginModule.
      3. Select Use login module proxy .
      4. Click OK.
      5. Click New, and then select com.ibm.ws.wssecurity.wssapi.token.impl.LTPAGenerateLoginModule.
      6. Click OK.
      7. Click JAAS - System logins.
  4. Configure your LTPA token generator to use the new JAAS configuration.
    1. Open your bindings configuration that you want to change.

      In the administrative console, select WS-Security > Authentication and protection.

    2. Under Authentication tokens, select the outbound LTPA token that you want to change.
    3. Select JAAS login = test.generate.ltpa.
    4. Click Save.
    5. Restart the application server to apply the JAAS configuration changes.
    6. Test your service.