Add string attributes to the default authorization token
Overview
We can use the default authorization token as a place to add string attributes that get propagated downstream.
The attributes added to the authorization token should be specific to the user associated with the authenticated Subject. If not, the attributes probably belong in the propagation token, which is also propagated with the request.
To add attributes into the authorization token, plug in a custom login module into the various system login modules that are configured. Any login module configuration that has the implementation...
com.ibm.ws.security.server.lm.wsMapDefaultInboundLoginModule
...can receive propagated information and can generate propagation information that can be sent outbound to another server.
If propagated attributes are not presented to the login configuration during an initial login, a default authorization token is created in the login module:
wsMapDefaultInboundLoginModule
...after the login occurs in the ltpaLoginModule login module. We can obtain a reference to the default authorization token from the login method using the sharedState hashmap. You must plug in the custom login module after the wsMapDefaultInboundLoginModule implementation for WAS to see the default authorization token.
Procedure
- Obtain a reference to the default authorization token from the login method.
- Add attributes to the token.
- Read existing attributes used for authorization.
- Verify the custom login module code is trusted.
Whenever you plug a custom login module into the WAS login infrastructure, verify the code is trusted. When you add the login module into the APP_ROOT/classes directory, it has Java 2 Security AllPermissions permissions. IBM recommends that you add the login module and other infrastructure classes into a private directory. However, if we use a private directory, modify...
$(WAS_INSTALL_ROOT)/properties/server.policy
...so that the private directory, JAR file, or both have the permissions that are needed to run the APIs that are called from the login module. Because the login module might run after the application code on the call stack, we might consider adding a doPrivileged code block so that you do not need to add additional permissions to the applications.
- Modify the authorization token factory to use a token factory other than the default token factory.
When WAS generates a default authorization token, the appserver utilizes the TokenFactory class specified using the com.ibm.wsspi.security.token.authorizationTokenFactory property.
The default token factory is:
com.ibm.ws.security.ltpa.AuthzPropTokenFactory token
This token factory encodes the data, but does not encrypt the data in the authorization token. Because the authorization token typically flows over CSIv2 using SSL, encrypting the token is not necessary. However, if we need additional security for the authorization token, we can associate a different token factory implementation with this property to get encryption. For example, if we associate the token factory...
com.ibm.ws.security.ltpa.LTPAToken2Factory
...with this property, the token uses Advanced Encryption Standard (AES) encryption. However, we need to weigh the performance impacts against the security needs. Adding sensitive information to the authorization token is one reason to change the token factory implementation to something that encrypts rather than just encodes.
- Open the admin console and go to...
Security | Global security | Additional properties | Custom properties
- To perform your own signing and encryption of the default authorization token, implement the following classes:
- com.ibm.wsspi.security.ltpa.Token
- com.ibm.wsspi.security.ltpa.TokenFactory
Your token factory implementation instantiates and validates your token implementation. Use the LTPA keys passed into the initialize method of the token factory or we can use our own keys. If we use our own keys, they must be the same everywhere to validate the tokens that are generated using those keys.
- To associate the token factory with the default authorization token, go to:
Security | Global security | Additional properties | Custom properties
...and verify...
com.ibm.wsspi.security.token.authorizationTokenFactory
...matches the custom token factory implementation.
- Verify the implementation classes are put into APP_ROOT/classes so the WAS class loader can load the classes.
- Verify the implementation classes are put into ${USER_INSTALL_ROOT}/classes so the class loader can load the classes.
Example
The following example shows the complete task of obtaining a reference to the default authorization token from the login method, adding attributes to the token, and reading from the existing attributes that are used for authorization.
public customLoginModule() { public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { // (.See on initialization, see // Develop custom login modules for a system login configuration for JAAS.) // Get a reference to the sharedState map that is passed in during initialization. _sharedState = sharedState; } public boolean login() throws LoginException { // (
See on what to do during login, see // Develop custom login modules for a system login configuration for JAAS.) // Look for the default AuthorizationToken in the shared state defaultAuthzToken = (com.ibm.wsspi.security.token.AuthorizationToken) sharedState.get (com.ibm.wsspi.security.auth.callback.Constants.WSAUTHZTOKEN_KEY); // Might not always have one of these generated. It depends on the login // configuration setup. if (defaultAuthzToken != null) { try { // Add a custom attribute defaultAuthzToken.addAttribute("key1", "value1"); // Determine all of the attributes and values that exist in the token. java.util.Enumeration listOfAttributes = defaultAuthorizationToken. getAttributeNames(); while (listOfAttributes.hasMoreElements()) { String key = (String) listOfAttributes.nextElement(); String[] values = (String[]) defaultAuthorizationToken.getAttributes (key); for (int i=0; i<values.length; i++) { System.out.println ("Key: " + key + ", Value[" + i + "]: " + values[i]); } } // Read the existing uniqueID attribute. String[] uniqueID = defaultAuthzToken.getAttributes (com.ibm.wsspi.security.token.AttributeNameConstants. WSCREDENTIAL_UNIQUEID); // Getthe uniqueID from the String[] String unique_id = (uniqueID != null && uniqueID[0] != null) ? uniqueID[0] : ""; // Read the existing expiration attribute. String[] expiration = defaultAuthzToken.getAttributes (com.ibm.wsspi.security.token.AttributeNameConstants. WSCREDENTIAL_EXPIRATION); // An example of getting a long expiration value from the string array. long expire_time = 0; if (expiration != null && expiration[0] != null) expire_time = Long.parseLong(expiration[0]); // Read the existing display name attribute. String[] securityName = defaultAuthzToken.getAttributes (com.ibm.wsspi.security.token.AttributeNameConstants. WSCREDENTIAL_SECURITYNAME); // Get the display name from the String[] String display_name = (securityName != null && securityName[0] != null) ? securityName[0] : ""; // Read the existing long securityName attribute. String[] longSecurityName = defaultAuthzToken.getAttributes (com.ibm.wsspi.security.token.AttributeNameConstants. WSCREDENTIAL_LONGSECURITYNAME); // Get the long security name from the String[] String long_security_name = (longSecurityName != null && longSecurityName[0] != null) ? longSecurityName[0] : ""; // Read the existing group attribute. String[] groupList = defaultAuthzToken.getAttributes (com.ibm.wsspi.security.token.AttributeNameConstants. WSCREDENTIAL_GROUPS); // Get the groups from the String[] ArrayList groups = new ArrayList(); if (groupList != null) { for (int i=0; i<groupList.length; i++) { System.out.println ("group[" + i + "] = " + groupList[i]); groups.add(groupList[i]); } } } catch (Exception e) { throw new WSLoginFailedException (e.getMessage(), e); } } } public boolean commit() throws LoginException { // (
See on what to do during commit, see // Develop custom login modules for a system login configuration for JAAS.) } private java.util.Map _sharedState = null; private com.ibm.wsspi.security.token.AuthorizationToken defaultAuthzToken = null; }
Related tasks
Authenticate users
Develop custom login modules for a system login configuration for JAAS
Propagating security attributes among appservers
Related
Use the default propagation token
Security: Links