+

Search Tips   |   Advanced Search

Develop web services applications to use a UsernameToken with no registry interaction

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

This information applies only to JAX-RPC web services.

By default, the default JAAS login module used with the web Services Security UsernameToken consumer, UsernameLoginModule, always validates the user name and password contained within the token against the WebSphere registry. We can configure a custom property to circumvent this registry check. When a caller part is added to the WS-Security constraints for a service provider, the user name and password contained in the UsernameToken are also validated against the WebSphere registry. This validation occurs in the com.ibm.ws.security.server.lm.ltpaLoginModule module that is part of the system.DEFAULT JAASconfiguration stack, as shown in the following example.

com.ibm.ws.security.server.lm.ltpaLoginModule
com.ibm.ws.security.server.lm.wsMapDefaultInboundLoginModule

The WebSphere Application Server WS-Security run time does not support the use of a JAAS configuration for the caller part that does not include these two login modules. However, we can add our own custom login modules to this JAAS configuration stack.

To use a UsernameToken with a caller part without accessing the WAS registry, prevent both the UsernameLoginModule and ltpaLoginModule modules from accessing the registry.

When a UsernameToken is added to a provider application using the wizard in an application developer, it automatically adds a caller part for the UsernameToken. A caller part is only needed if we want the identity from the UsernameToken to be on the thread of execution. If the application does not require the identity from the UsernameToken to be on the thread of execution, then we do not need the caller part and can remove it. The caller part is configured in the deployment descriptor extensions and can be accessed only with an application developer

Refer to the "Configuring the caller in consumer security constraints" topic in the IBM Rational Application Developer information center.

  1. To prevent the UsernameLoginModule module from accessing the registry, add the com.ibm.wsspi.wssecurity.auth.module.UsernameLoginModule.disableUserRegistryCheck custom property to the JAAS configuration for the UsernameToken consumer. We can add this custom property in one of two ways:

    The update to the wssecurity.UsernameToken JAAS configuration causes all users of this JAAS configuration on the application server to not check the registry. If we do not want this behavior, create a new JAAS configuration or use the method to update the UsernameToken consumergotcha

    To add the custom property to the com.ibm.wsspi.wssecurity.auth.module.UsernameLoginModule module in the wssecurity.UsernameToken JAAS configuration:

    1. Click Security > Global security > Authentication, click Java Authentication and Authorization Service > System logins.

    2. Select wssecurity.UsernameToken.

    3. Select com.ibm.wsspi.wssecurity.auth.module.UsernameLoginModule.

    4. Add the following custom property: com.ibm.wsspi.wssecurity.auth.module.UsernameLoginModule.disableUserRegistryCheck=true.

    5. Click OK.

    6. Restart the application server to reload the updated JAAS configuration.

    To add the custom property to the application's token consumer, perform the following steps:

    1. Click Applications > Application Types > WebSphere enterprise applications > (providerAppName) > Manage Modules > (moduleName) > Web services: Server security bindings.

    2. Under Request consumer (receiver) binding, click Edit custom > Token consumers.

    3. Select the UsernameToken consumer.

    4. Click JAAS configuration > Properties > New.

    5. Add the following custom property: com.ibm.wsspi.wssecurity.auth.module.UsernameLoginModule.disableUserRegistryCheck=true.

    6. Click OK.

    7. Click Save.

    8. Restart the application.

    If the UsernameToken consumer's name looks like 'Token_123' and is not selectable, then the application developer that you used to add the security constraints failed to give a name to the token consumer in the deployment descriptor. Alternatively, we can perform one of the following two options.

    1. Add the property to the security JAAS configuration as described in step 1.

    2. Edit the deployment descriptor bindings in the application project using an application developer.
    Refer to the "Configuring the security token requirement in consumer security constraints" topic in the IBM Rational Application Developer information center.

  2. Develop a JAAS login module that stacks above com.ibm.ws.security.server.lm.ltpaLoginModule. The following example shows sample code for the JAAS login module:
    package test.tokens;
    import java.util.Map;
    import java.util.Hashtable;
    
    import javax.security.auth.Subject;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
    import javax.security.auth.callback.NameCallback;
    import javax.security.auth.callback.PasswordCallback;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import com.ibm.wsspi.wssecurity.auth.token.UsernameToken;
    import com.ibm.wsspi.security.token.AttributeNameConstants;
    
    public class MyAuthLoginModule implements LoginModule {
    
       private Map _sharedState = null;
       private CallbackHandler _callbackHandler = null;
       Subject _subject = null;
    
    
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
         this._sharedState = sharedState;  
         this._callbackHandler = callbackHandler;
         this._subject = subject;  
     }
    
     public boolean login() throws LoginException {
         //For the sake of readability, this login module does not      //protect against all NPE's
    
         String username = null;
         char [] password = null;
         NameCallback nameCallback = null;
         PasswordCallback passwordCallback = null;
    
         //Get the username and password from callbacks that      //the ws-security runtime set up
         Callback[] callbacks = new Callback[2];
         callbacks[0] = nameCallback = new NameCallback("Username: ");
         callbacks[1] = passwordCallback = new PasswordCallback("Password: ", false);
         try {
           _callbackHandler.handle(callbacks);
         } catch ( Exception e ) {
           throw new LoginException("Unable to process callbacks");
         }
    
         if (nameCallback != null) {
           username = nameCallback.getName();
         }
    
         if (passwordCallback != null) {
           char tmp[] = passwordCallback.getPassword();
           if (tmp != null && tmp.length != 0) {
             password = new char[tmp.length];
             System.arraycopy(tmp, 0, password, 0, tmp.length);
           }
         }
    
         if (username == null) {
           throw new LoginException("Unable to obtain username");
         }
    
         //If we will be validating the username and password, //validate it here
    
         Hashtable customProperties = (Hashtable)_sharedState.get(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY);
         if (customProperties == null) {
           customProperties = new Hashtable();
          _sharedState.put(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY, customProperties);
         }
    
        // Default realm is used here, but any trusted realm can be used     String uid = "defaultWIMFileBasedRealm/" + username;
        customProperties.put(AttributeNameConstants.WSCREDENTIAL_UNIQUEID, uid)
        // SECURITYNAME will be the principal name     customproperties.put(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME, username);
    
         return true;
       }
    
     public boolean logout() throws LoginException {
      return false;
     }
    
    }

  3. Create a JAAS login configuration.

    1. In the console, select Security > Global security > Authentication, select Java Authentication and Authorization Service > System logins.

    2. Click New, and under Aliases, enter test.auth.jaxrpcunt.

    3. Add the JAAS login modules. We must add the following login modules in the order shown:

        test.tokens.MyAuthLoginModule

      The name of this module must match the JAAS login module that you developed.

      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. Restart the application server to apply the JAAS configuration changes.

  5. Configure the caller part to use the new JAAS configuration. We can configure the caller part by using only an application developer. Refer to the "Configuring the caller in consumer security constraints" topic in the IBM Rational Application Developer information center.

    • Add the following custom property to the caller part for the UsernameToken: com.ibm.wsspi.wssecurity.Caller.assertionLoginConfig=system.test.auth.jaxrpcunt.

    • Save the deployment descriptor

    • Redeploy the application to the server

  6. Test the service.


Related concepts

  • Security token
  • Development and assembly tools


    Related tasks

  • Develop web services clients that retrieve tokens from the JAAS Subject in an application
  • Protecting system resources and APIs (Java 2 security) for developing applications
  • Configure Java 2 security policy files


    Related information:

  • Rational Application Developer documentation
  • Configure the caller in consumer security constraints