For inbound identity mapping, write a custom login module and configure WebSphere Application Server to run the login module first within the system login configurations. Consider the following steps when you write your custom login module.
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 you 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. 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 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); }
boolean requiresLogin = ((com.ibm.wsspi.security.auth.callback.WSTokenHolderCallback) callbacks[2]).requiresLogin();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, you can choose to discontinue processing as the necessary information exists to create the Subject without performing additional remote user registry calls.
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 that is 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 you are using. If you 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. You must 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 that is 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:
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:
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 WebSphere Application Server default implementation for the unique ID value, call the WebSphere Application Server public String getUniqueUserId(String userSecurityName) UserRegistry method.
Realm | Format (uniqueUserId) |
---|---|
Lightweight Directory Access Protocol (LDAP) | ldaphost.austin.ibm.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.
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.
Realm | Format |
---|---|
LDAP | ldap1.austin.ibm.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.
This com.ibm.wsspi.security.cred.cacheKey property is not required. When this property is not specified, the cache lookup is the value that is specified for WSCREDENTIAL_UNIQUEID. When this information is found in the java.util.Hashtable object, WebSphere Application Server 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.
ExampleThe
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 WebSphere Application Server login modules can locate the information in the hashtable.
Related reference
Custom login module development for a system login configuration
getRemoteUser and getAuthType methods