Example: Custom login module for inbound mapping

This sample 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 WebSphere® Application Server login modules can locate the information in the Hashtable.

public customLoginModule() 
{

public void initialize(Subject subject, CallbackHandler callbackHandler, 
   Map sharedState, Map options) 
{
	// (For more information on initialization, see 
	//  Developing custom login modules for a system login configuration for JAAS.)
	_sharedState = sharedState;
}

public boolean login() throws LoginException 
{
	// (For more information on what to do during login, see 
	//  Developing custom login modules for a system login configuration for JAAS.)

   // Handles the WSTokenHolderCallback to see if this is an initial or 
   // propagation login.
	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 the exception
	} 

	// Determines 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);
       // Set the string to the UID so you can use the information to either 
       // map or login.
			uid = WSSecurityPropagationHelper.getUserFromUniqueID (uniqueid);
		}
		catch (Exception e)
		{
			// handle exception
		}	
	}
	else if (uid == null)
	{
		// The 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. You can choose to map this ID to
     // another ID or you can skip it and allow WebSphere Application Server
     // to log in for you. When passwords are presented, be very careful not
     // to validate the password because this is the initial authentication.
		
		return true;
	}

  // You can map this uid to something else and set the identitySwitched 
  // boolean. If the identity is changed, clear the following propagated 
  // attributes so they are not used incorrectly.
	uid = myCustomMappingRoutine (uid);
	
	// Clear the propagated attributes because they no longer apply to the new identity
	if (identitySwitched)
	{
		((WSTokenHolderCallback) callbacks[3]).setTokenHolderList(null);
	}
	boolean requiresLogin = ((com.ibm.wsspi.security.auth.callback.
     WSTokenHolderCallback) callbacks[2]).getRequiresLogin();

	if (requiresLogin || identitySwitched)
	{
		// Retrieves the default InitialContext for this server.
		javax.naming.InitialContext ctx = new javax.naming.InitialContext();

		// Retrieves the local UserRegistry object.
		com.ibm.websphere.security.UserRegistry reg = 
         (com.ibm.websphere.security.UserRegistry) ctx.lookup("UserRegistry");				

		// Retrieves the registry uniqueID based on the uid that is 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 this uniqueID.
		java.util.List groupList = reg.getUniqueGroupIds(uid);
			
		// Creates the java.util.Hashtable with the information that you gathered 
     // from the UserRegistry.
		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 that is used as part of the lookup mechanism for 
		// the created Subject. The cache key can be an object, but has  
		// an implemented toString method. Make sure the cacheKey contains enough 
		// information to scope it to the user and any additional attributes you are 
     // using. If you do not specify this property, the Subject is scoped to the
		// WSCREDENTIAL_UNIQUEID returned, by default.
		hashtable.put(com.ibm.wsspi.security.token.AttributeNameConstants.
       WSCREDENTIAL_CACHE_KEY, "myCustomAttribute" + uniqueid);
		// Adds the hashtable to the shared state of the Subject.
		_sharedState.put(com.ibm.wsspi.security.token.AttributeNameConstants.
       WSCREDENTIAL_PROPERTIES_KEY, hashtable);
	}
	else if (requiresLogin == false)
	{
		// For more information on this section, see 
     // Security attribute propagation.
		// If you added a custom Token implementation, you can search through the 
     // token holder list for it to deserialize.
		// Note: Any Java objects are automatically deserialized by 
     // wsMapDefaultInboundLoginModule
		
		for (int i=0; i<authzTokenList.size(); i++)
		{
			TokenHolder tokenHolder = (TokenHolder) authzTokenList.get(i);
			if (tokenHolder.getName().equals("com.acme.MyCustomTokenImpl"))
			{
						byte[] myTokenBytes = tokenHolder.getBytes();

          // Passes these bytes into the constructor of your implementation 
          // class for deserialization.
						com.acme.MyCustomTokenImpl myTokenImpl = new com.acme.MyCustomTokenImpl(myTokenBytes);
			}
		}
	}
}

public boolean commit() throws LoginException 
{
	// (For more information on what to do during a commit, see
  //   Developing custom login modules for a system login configuration for JAAS.)
}

// Defines your login module variables
com.ibm.wsspi.security.token.AuthorizationToken customAuthzToken = null;
com.ibm.wsspi.security.token.AuthenticationToken defaultAuthToken = null;
java.util.Map _sharedState = null;
}