Set inbound identity mapping


For inbound identity mapping, write a custom login module and configure WAS to run the login module first within the system login configurations. Consider the following steps when you write the custom login module.

 

  1. Get the inbound user identity from the callbacks and map the identity, if necessary This step occurs in the login method of the login module. A valid authentication has either or both NameCallback and the WSCredTokenCallback callbacks present.

    The following code sample shows you how to determine the user identity:

    javax.security.auth.callback.Callback callbacks[] = 
       new javax.security.auth.callback.Callback[3];
      callbacks[0] = new javax.security.auth.callback.NameCallback("");
      callbacks[1] = new javax.security.auth.callback.PasswordCallback
         ("Password: ", false);
      callbacks[2] = new com.ibm.websphere.security.auth.callback.
         WSCredTokenCallbackImpl("");
      callbacks[3] = new com.ibm.wsspi.security.auth.callback.
         WSTokenHolderCallback("");
    
      try
      {
        callbackHandler.handle(callbacks);
      } 
      catch (Exception e)
      {
        
    // Handles exceptions
        throw new WSLoginFailedException (e.getMessage(), e);
      }
    
      
    // Shows which callbacks contain information
      boolean identitySwitched = false;
      String uid = ((NameCallback) callbacks[0]).getName();
      char password[] = ((PasswordCallback) callbacks[1]).getPassword();
      byte[] credToken = ((WSCredTokenCallbackImpl) callbacks[2]).getCredToken();
      java.util.List authzTokenList = ((WSTokenHolderCallback) 
         callbacks[3]).getTokenHolderList();
    
      if (credToken != null)
      {
        try
        {
          String uniqueID = WSSecurityPropagationHelper.validateLTPAToken(credToken);
          String realm = WSSecurityPropagationHelper.getRealmFromUniqueID (uniqueID);
           
    // Now set the string to the UID so that we can use the result for either
           
    // mapping or logging in.
          uid = WSSecurityPropagationHelper.getUserFromUniqueID (uniqueID);
        }
        catch (Exception e)
        {
          
    // Handles the exception
        }  
      }
      else if (uid == null)
      {
         
    // Throws an exception if authentication data is not valid.
         
    // You must have either UID or CredToken
        throw new WSLoginFailedException("invalid authentication data.");
      }
      else if (uid != null && password != null)
      {
         
    // This is a typical authentication. We can choose to map this ID to  
         
    // another ID or we can skip it and allow WAS 
         
    // to log in for you. When passwords are presented, be very careful to not 
         
    // validate the password because this is the initial authentication.
        
        return true;
      }
    
        
    // If desired, map this uid to something else and set the identitySwitched 
        
    // boolean. If the identity was changed, clear the propagated attributes 
        
    // below so they are not used incorrectly.
      uid = myCustomMappingRoutine (uid);
      
        
    // Clear the propagated attributes because they are no longer applicable 
        
    // to the new identity
      if (identitySwitched)
      {
        ((WSTokenHolderCallback) callbacks[3]).setTokenHolderList(null);
      }
    
    

  2. Check to see if attribute propagation occurred and if the attributes for the user are already present when the identity remains the same. Check to see if the user attributes are already present from the sending server to avoid duplicate calls to the user registry lookup. To check for the user attributes, use a method on the WSTokenHolderCallback callback that analyzes the information present in the callback to determine if the information is sufficient for WAS to create a Subject.

    The following code sample checks for the user attributes:

    boolean requiresLogin =  ((com.ibm.wsspi.security.auth.callback.WSTokenHolderCallback)  callbacks[2]).getrequiresLogin();
    

    If sufficient attributes are not present to form the WSCredential and the WSPrincipal objects that are needed to perform authorization, the previous code sample returns a true result. When the result is false, we can choose to discontinue processing as the necessary information exists to create the Subject without performing additional remote user registry calls.

  3. Look up the required attributes from the user registry, put the attributes in a hashtable, and add the hashtable to the shared state. If the identity is switched in this login module, complete the following steps:

    1. Create the hashtable of attributes, as shown in the following example.

    2. Add the hashtable to the shared state.

    If the identity is not switched, but the value of the requiresLogin code sample shown previously is true, we can create the hashtable of attributes. However, we are not required to create a hashtable in this situation as WAS handles the login for you. However, we might consider creating a hashtable to gather attributes in special cases where we are using our own special user registry. Creating a UserRegistry implementation, using a hashtable, and letting WAS gather the user attributes for we might be the easiest solution.

    The following table shows how to create a hashtable of user attributes:

    if (requiresLogin || identitySwitched)
      {
        
    // Retrieves the default InitialContext for this server.
        javax.naming.InitialContext ctx = new javax.naming.InitialContext();
    
        
    // Retrieves the local UserRegistry implementation.
        com.ibm.websphere.security.UserRegistry reg = (com.ibm.websphere.
            security.UserRegistry) 
        ctx.lookup("UserRegistry");        
    
         
    // Retrieves the user registry uniqueID based on the uid specified
         
    // in the NameCallback.
        String uniqueid = reg.getUniqueUserId(uid);
         uid = WSSecurityPropagationHelper.getUserFromUniqueID (uniqueid);
          
         
    // Retrieves the display name from the user registry based on the uniqueID.
        String securityName = reg.getUserSecurityName(uid);
      
         
    // Retrieves the groups associated with the uniqueID.
        java.util.List groupList = reg.getUniqueGroupIds(uid);
          
         
    // Creates the java.util.Hashtable with the information that you gathered 
         
    // from the UserRegistry implementation.
        java.util.Hashtable hashtable = new java.util.Hashtable();
        hashtable.put(com.ibm.wsspi.security.token.AttributeNameConstants.
           WSCREDENTIAL_UNIQUEID, uniqueid);
         hashtable.put(com.ibm.wsspi.security.token.AttributeNameConstants.
           WSCREDENTIAL_SECURITYNAME, securityName);
        hashtable.put(com.ibm.wsspi.security.token.AttributeNameConstants.
           WSCREDENTIAL_GROUPS, groupList);
    
         
    // Adds a cache key used as part of the lookup mechanism for 
         
    // the created Subject. The cache key can be an object, but should have 
         
    // an implemented toString method. Make sure that the cacheKey contains 
         
    // enough information to scope it to the user and any additional attributes 
         
    // that we are using. If we do not specify this property the Subject is 
         
    // scoped to the returned WSCREDENTIAL_UNIQUEID, by default.
        hashtable.put(com.ibm.wsspi.security.token.AttributeNameConstants.
            WSCREDENTIAL_CACHE_KEY, "myCustomAttribute" + uniqueid);
        
    // Adds the hashtable to the sharedState of the Subject.
        _sharedState.put(com.ibm.wsspi.security.token.AttributeNameConstants.
            WSCREDENTIAL_PROPERTIES_KEY, hashtable);
      }
    
    

    The following rules define in more detail how a hashtable login is performed. Use a java.util.Hashtable object in either the Subject (public or private credential set) or the shared-state HashMap. The com.ibm.wsspi.security.token.AttributeNameConstants class defines the keys that contain the user information. If the Hashtable object is put into the shared state of the login context using a custom login module listed prior to the Lightweight Third Party Authentication (LTPA) login module, the value of the java.util.Hashtable object is searched using the following key within the shared-state hashMap:

    Property

    com.ibm.wsspi.security.cred.propertiesObject

    Reference to the property

    AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY

    Explanation

    This key searches for the Hashtable object that contains the required properties in the shared state of the login context.

    Expected result

    A java.util.Hashtable object.

    If a java.util.Hashtable object is found either inside the Subject or within the shared state area, verify that the following properties are present in the hashtable:

    Property

    com.ibm.wsspi.security.cred.uniqueId

    Reference to the property

    AttributeNameConstants.WSCREDENTIAL_UNIQUEID

    Returns

    java.util.String

    Explanation

    The value of the property must be a unique representation of the user. For the WAS default implementation, this property represents the information that is stored in the application authorization table. The information is located in the application deployment descriptor after it is deployed and user-to-role mapping is performed. See the expected format examples if the user to role mapping is performed using a lookup to a WAS user registry implementation.

    If a third-party authorization provider overrides the user-to-role mapping, then the third-party authorization provider defines the format. To ensure compatibility with the WAS default implementation for the unique ID value, call the WAS public String getUniqueUserId(String userSecurityName) UserRegistry method.

    Expected format examples


    Table 1. Format examples

    Realm Format (uniqueUserId)
    LDAP ldaphost.mpls.setgetweb.com:389/cn=user,o=ibm,c=us
    Windows MYWINHOST/S-1-5-21-963918322-163748893-4247568029-500
    UNIX MYUNIXHOST/32

    The com.ibm.wsspi.security.cred.uniqueId property is required.

    Property

    com.ibm.wsspi.security.cred.securityName

    Reference to the property

    AttributeNameConstants. WSCREDENTIAL_ SECURITYNAME

    Returns

    java.util.String

    Explanation

    This property searches for the securityName of the authentication user. This name is commonly called the display name or short name. WAS uses the securityName attribute for the getRemoteUser, getUserPrincipal and getCallerPrincipal APIs. To ensure compatibility with the WAS default implementation for the securityName value, call the WAS public String getUserSecurityName(String uniqueUserId) UserRegistry method.

    Expected format examples


    Table 2. Format examples

    Realm Format (uniqueUserId)
    LDAP user (LDAP UID)
    Windows user (Windows username)
    UNIX user (UNIX username)

    The com.ibm.wsspi.security.cred.securityName property is required.

    Property

    com.ibm.wsspi.security.cred.groups

    Reference to the property

    AttributeNameConstants. WSCREDENTIAL_GROUPS

    Returns

    java.util.ArrayList

    Explanation

    This key searches for the array list of groups to which the user belongs. The groups are specified in the realm_name/user_name format. The format of these groups is important as the groups are used by the WAS authorization engine for group-to-role mappings in the deployment descriptor. The format that is provided must match the format expected by the WAS default implementation. When you use a third-party authorization provider, use the format that is expected by the third-party provider. To ensure compatibility with the WAS default implementation for the unique group IDs value, call the WAS public List getUniqueGroupIds(String uniqueUserId) UserRegistry method.

    Expected format examples for each group in the array list


    Table 3. Format examples

    Realm Format
    LDAP ldap1.mpls.setgetweb.com:389/cn=group1,o=ibm,c=us
    Windows MYWINREALM/S-1-5-32-544
    UNIX MY/S-1-5-32-544

    The com.ibm.wsspi.security.cred.groups property is not required. A user is not required to have associated groups.

    Property

    com.ibm.wsspi.security.cred.cacheKey

    Reference to the property

    AttributeNameConstants. WSCREDENTIAL_CACHE_KEY

    Returns

    java.lang.Object

    Explanation

    This key property can specify an object that represents the unique properties of the login, including the user-specific information and the user dynamic attributes that might affect uniqueness. For example, when the user logs in from location A, which might affect their access control, the cache key needs to include location A so that the Subject that is received is the correct Subject for the current location.

    This com.ibm.wsspi.security.cred.cacheKey property is not required. When this property is not specified, the cache lookup is the value specified for WSCREDENTIAL_UNIQUEID. When this information is found in the java.util.Hashtable object, WAS creates a Subject similar to the Subject that goes through the normal login process at least for LTPA. The new Subject contains a WSCredential object and a WSPrincipal object that is fully populated with the information found in the Hashtable object.

  4. Add the custom login module into the RMI_INBOUND, WEB_INBOUND, and DEFAULT Java Authentication and Authorization Service (JAAS) system login configurations. Set the RMI_INBOUND login configuration so that WAS loads the new custom login module first.

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

    2. Under Additional Properties, click JAAS login modules > New to add the login module to the RMI_INBOUND configuration.

    3. Return to the JAAS login modules panel for RMI_INBOUND.

    4. Click Set order to change the order that the login modules are loaded so that WAS loads the custom login module first. Use the Move Up or Move Down buttons to arrange the order of the login modules.

    5. Repeat the previous three steps for the WEB_INBOUND and DEFAULT login configurations.

 

Results

This process configures identity mapping for an inbound request.

 

Example

The Example: Custom login module for inbound mapping topic shows a custom login module that creates a java.util.Hashtable hashtable that is based on the specified NameCallback callback. The java.util.Hashtable hashtable is added to the sharedState java.util.Map map so that the WAS login modules can locate the information in the hashtable.


Example: Custom login module for inbound mapping

 

Related tasks


Develop custom login modules for a system login configuration for JAAS
Performing identity mapping for authorization across servers in different realms

 

Related


getRemoteUser and getAuthType methods