Configuring a UsernameToken caller configuration with no registry interaction

To authenticate a UsernameToken with a caller configuration without accessing the WebSphere® registry, you can replace the authentication method of the UsernameToken consumer and configure the caller to use an alternative JAAS login configuration.

About this task

This information applies only to Java API for XML Web Services (JAX-WS).

By default, the JAX-WS Web Services Security UsernameToken consumer, UNTConsumeLoginModule, always validates the user name and password that are contained within the token against the WebSphere registry. You can use the SPIs that GenericSecurityTokenFactory provides to replace this authentication method with one of your own. For more information, see Replacing the authentication method of the UsernameToken consumer using a stacked JAAS login module.

When a caller configuration is added to the WS-Security constraints for a service provider, the user name and password that are contained in the UsernameToken are also validated against the WebSphere registry. If a user name and password are provided, both the user name and password are validated against the WebSphere registry. If only a user name is provided, the user name must exist in the WebSphere registry. These validations occur in the com.ibm.ws.security.server.lm.ltpaLoginModule module that is part of the wss.caller Java™ Authentication and Authorization Service (JAAS) configuration stack, as shown in the following example:

com.ibm.ws.wssecurity.impl.auth.module.PreCallerLoginModule
com.ibm.ws.wssecurity.impl.auth.module.UNTCallerLoginModule
...
com.ibm.ws.wssecurity.impl.auth.module.WSWSSLoginModule
com.ibm.ws.security.server.lm.ltpaLoginModule
com.ibm.ws.security.server.lm.wsMapDefaultInboundLoginModule

The WebSphere WS-Security run time does not support using JAAS configuration for the caller that does not include the ltpaLoginModule and wsMapDefaultInboundLoginModule login modules.

To use a UsernameToken with a caller configuration without accessing the WebSphere registry, you must prevent the UNTConsumeLoginModule and ltpaLoginModule modules from accessing the registry and provide alternative modules.

Procedure

  1. To prevent the UNTConsumeLoginModule module from accessing the registry, replace the authentication method of the UsernameToken consumer. For more information, see twbs_replace_authmethod_usernametoken.html.
  2. Develop a JAAS login module that stacks above com.ibm.ws.wssecurity.impl.auth.module.WSWSSLoginModule.
    The following example shows example code for a JAAS login module:
    package test.tokens;
    
    import java.util.Map;
    import java.util.Hashtable;
    
    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.SecurityToken;
    import com.ibm.wsspi.security.token.AttributeNameConstants;
    import com.ibm.wsspi.security.registry.RegistryHelper;
    import com.ibm.websphere.security.UserRegistry;
    
    public class MyAuthLoginModule implements LoginModule {
    
      private Map<String, ?> _sharedState;
    
      public void initialize(Subject subject, CallbackHandler callbackHandler,
                             Map<String, ?> sharedState, Map<String, ?> options) {
    
        this._sharedState = sharedState;  
      }
    
      public boolean login() throws LoginException {
        //For the sake of readability, this login module does not
        //protect against all NPE's
    
    	String username = null;
    	  
    	// get the caller token
    	SecurityToken callerIdentityToken = (SecurityToken)this._sharedState.get(
    	    com.ibm.wsspi.wssecurity.core.Constants.WSSECURITY_CALLER_IDENTITY);
    
    	// if its a UsernameToken, get the username
    	if (callerIdentityToken instanceof UsernameToken) {
    	  username = ((UsernameToken)callerIdentityToken).getUsername();
    	}
    	if (username == null) {
    	  throw new LoginException("Unable to obtain username");
    	}
    
    	Hashtable customProperties = (Hashtable)_sharedState.get(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY);
    	if (customProperties == null) {
    	  customProperties = new Hashtable();
    	}
    // Get the default realm
    String defaultRealm = null;
    try {
      UserRegistry reg = RegistryHelper.getUserRegistry(null);
      defaultRealm = reg.getRealm();
    } catch (Exception e) {
      LoginException le = new LoginException(e.toString());
      le.initCause(e);
      throw le;
    }
    String uid = defaultRealm + username;
    
    // setting the UNIQUEID makes ltpaLoginModule skip the registry check
    customProperties.put(AttributeNameConstants.WSCREDENTIAL_UNIQUEID, uid);
    
    // SECURITYNAME will be the principal name	            
    customProperties.put(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME, username);
    
    sharedState.put(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY, customProperties);
    
    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, go to Security > Global security.
    2. Under Authentication, go to Java Authentication and Authorization Service > System logins.
    3. Click New, and under Alias, enter test.auth.unt.
    4. Add the JAAS login modules.
      You must add the following login modules in the order shown:
      • com.ibm.ws.wssecurity.impl.auth.module.PreCallerLoginModule
      • com.ibm.ws.wssecurity.impl.auth.module.UNTCallerLoginModule
      • test.tokens.MyAuthLoginModule
        Important: The name of this module must match the JAAS login module that you developed.
      • com.ibm.ws.wssecurity.impl.auth.module.WSWSSLoginModule
      • com.ibm.ws.security.server.lm.ltpaLoginModule
      • com.ibm.ws.security.server.lm.wsMapDefaultInboundLoginModule
      For each login module:
      1. Under JAAS login modules, click New.
      2. Under Module class name, enter the name of the login module.
      3. For test.tokens.MyAuthLoginModule only, select Use login module proxy.
      4. Click OK.
    5. Click OK, then Save.
  4. Configure your caller to use the new JAAS configuration.
    1. In the administrative console, open the bindings configuration that you want to change.
    2. Select WS-Security > Caller.
    3. Select the caller configuration that you want to change.
    4. Under JAAS login, select test.auth.unt.
    5. Click OK, then Save.
  5. Restart the application server to apply the JAAS configuration changes.
  6. Test the service.