Default PropagationToken
A default PropagationToken is located on the thread of execution for applications and the security infrastructure to use. WebSphere Application Server propagates this default PropagationToken downstream and the token stays on the thread where the invocation lands at each hop. The data should be available from within the container of any resource where the PropagationToken lands. Remember that enable the propagation feature at each server where a request is sent in order for propagation to work. Make sure that you have enabled security attribute propagation for all of the cells in your environment where you want propagation
There is a WSSecurityHelper class that has APIs for accessing the PropagationToken attributes. This article documents the usage scenarios and includes examples. A close relationship exists between PropagationToken and the WorkArea feature. The main difference between these features is that after you add attributes to the PropagationToken, one cannot change the attributes. We cannot change these attributes so that the security run time can add auditable information and have that information remain there for the life of the invocation. Any time that you add an attribute to a specific key, an ArrayList is stored to hold that attribute. Any new attribute added with the same key is added to the ArrayList. When you call getAttributes, the ArrayList is converted to a String[] and the order is preserved. The first element in the String[] is the first attribute added for that specific key.
In the default PropagationToken, a change flag is kept that logs any data changes to the token. These changes are tracked to enable WAS to know when to re-send the authentication information downstream so that the downstream server has those changes. Normally, CSIv2 (CSIv2) maintains a session between servers for an authenticated client. If the PropagationToken changes, a new session is generated and subsequently a new authentication occurs. Frequent changes to the PropagationToken during a method cause frequent downstream calls. If you change the token prior to making many downstream calls or you change the token between each downstream call, you might impact security performance.
Getting the server list from the default PropagationToken
Every time the PropagationToken is propagated and used to create the authenticated Subject, either horizontally or downstream, the name of the receiving application server is logged into the PropagationToken. The format of the host is "Cell:Node:Server", which provides you access to the cell name, node name, and server name of each application server that receives the invocation. The following code provides you with this list of names and can be called from a Java 2 Platform, Enterprise Edition (J2EE) application:
String[] server_list = null;
// If security is disabled on this application server, do not bother checking
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
// Gets the server_list string array
server_list = com.ibm.websphere.security.WSSecurityHelper.getServerList();
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
if (server_list != null)
{
// print out each server in the list, server_list[0] is the first server
for (int i=0; i<server_list.length; i++)
{
System.out.println("Server[" + i + "] = " + server_list[i]);
}
}
} The format of each server in the list is: cell:node:server. The output, for example, is: myManager:node1:server1
Getting the caller list from the default PropagationToken
A default PropagationToken is generated any time an authenticated user is set on the thread of execution or any one tries to add attributes to the PropagationToken. Whenever an authenticated user is set on the thread, the user is logged in the default PropagationToken. There may be some pushing and popping of Subjects by the authorization code. At times, the same user might be logged in multiple times if the RunAs user is different from the caller. The following list provides the rules that are used to determine if a user added to the thread gets logged into the PropagationToken:
- The current Subject must be authenticated. For example, an unauthenticated Subject is not logged.
- The current authenticated Subject is logged if a Subject has not been previously logged.
- The current authenticated Subject is logged if the last authenticated Subject logged does not contain the same user.
- The current authenticated Subject is logged on each unique application server involved in the propagation process.
The following code sample shows how to use the getCallerList() API:
String[] caller_list = null;
// If security is disabled on this application server, do not check the caller list
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
// Gets the caller_list string array
caller_list = com.ibm.websphere.security.WSSecurityHelper.getCallerList();
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
if (caller_list != null)
{
// Prints out each caller in the list, caller_list[0] is the first caller
for (int i=0; i<caller_list.length;i++)
{
System.out.println("Caller[" + i + "] = " + caller_list[i]);
}
}
}
The format of each caller in the list is: cell:node:server:realm:port_number/securityName. The output, for example, is: myManager:node1:server1:ldap.austin.ibm.com:389/jsmith.
Getting the first caller from the default PropagationToken
Whenever you want to know which authenticated caller started the request, one can call the getFirstCaller method and the caller list is parsed. However, this method returns the securityName of the caller only. If we need to know more than the securityName, call the getCallerList() method and retrieve the first entry in the String[]. This entry provides the entire caller information. The following code sample retrieves the securityName of the first authenticated caller using the getFirstCaller() API:
String first_caller = null;
// If security is disabled on this application server, do not bother checking
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
// Gets the first caller
first_caller = com.ibm.websphere.security.WSSecurityHelper.getFirstCaller();
// Prints out the caller name
System.out.println("First caller: " + first_caller);
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
}
The output, for example, is: jsmith.
Getting the first application server name from the default
PropagationTokenWhenever you want to know what the first application server is for this request, one can call the getFirstServer() method directly. The following code sample retrieves the name of the first application server using the getFirstServer() API:
String first_server = null;
// If security is disabled on this application server, do not bother checking
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
// Gets the first server
first_server = com.ibm.websphere.security.WSSecurityHelper.getFirstServer();
// Prints out the server name
System.out.println("First server: " + first_server);
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
}
The output, for example, is: myManager:node1:server1.
Adding custom attributes to the default
PropagationTokenWe can add custom attributes to the default PropagationToken for application usage. This token follows the request downstream so that the attributes are available when they are needed. When you use the default PropagationToken to add attributes, understand the following issues:
- When you add information to the PropagationToken, it affects CSIv2 session caching. Add information sparingly between remote requests.
- After you add information with a specific key, the information cannot be removed.
- We can add as many values to a specific key as your need. However, all of the values must be available from a returned String[] in the order they were added.
- The PropagationToken is available only on servers where propagation and security are enabled.
- The Java 2 Security javax.security.auth.AuthPermission wssecurity.addPropagationAttribute is needed to add attributes to the default PropagationToken.
- An application cannot use keys that begin with either com.ibm.websphere.security or com.ibm.wsspi.security. These prefixes are reserved for system usage.
The following code sample shows how to use the addPropagationAttribute API:
// If security is disabled on this application server,
// do not check the status of server security
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
// Specifies the key and values
String key = "mykey";
String value1 = "value1";
String value2 = "value2";
// Sets key, value1
com.ibm.websphere.security.WSSecurityHelper.
addPropagationAttribute (key, value1);
// Sets key, value2
String[] previous_values = com.ibm.websphere.security.WSSecurityHelper.
addPropagationAttribute (key, value2);
//Note: previous_values should contain value1
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
}
See Getting custom attributes from the default PropagationToken to retrieve attributes using the getPropagationAttributes application programming interface (API).
Getting custom attributes from the default
PropagationTokenCustom attributes are added to the default PropagationToken using the addPropagationAttribute API. These attributes can be retrieved using the getPropagationAttributes API. This token follows the request downstream so the attributes are available when they are needed. When you use the default PropagationToken to retrieve attributes, understand the following issues.
- The PropagationToken is available only on servers where propagation and security are enabled.
- The Java 2 Security javax.security.auth.AuthPermission wssecurity.getPropagationAttributes is needed to retrieve attributes from the default PropagationToken.
The following code sample shows how to use the getPropagationAttributes API:
// If security is disabled on this application server, do not bother checking
if (com.ibm.websphere.security.WSSecurityHelper.isServerSecurityEnabled())
{
try
{
String key = "mykey";
String[] values = null;
// Sets key, value1
values = com.ibm.websphere.security.WSSecurityHelper.
getPropagationAttributes (key);
// Prints the values
for (int i=0; i<values.length; i++)
{
System.out.println("Value[" + i + "] = " + values[i]);
}
}
catch (Exception e)
{
// Performs normal exception handling for your application
}
}
The output, for example, is:
Value[0] = value1
Value[1] = value2See Adding custom attributes to the default PropagationToken to add attributes using the addPropagationAttributes API.
Changing the TokenFactory associated with the default PropagationToken
When WebSphere Application Server generates a default PropagationToken, the application server utilizes the TokenFactory class that is specified using the com.ibm.wsspi.security.token.propagationTokenFactory property. To modify this property using the administrative console, complete the following steps:
- Click Security > Global Security.
- Under Additional properties, click Custom properties.
The default TokenFactory specified for this property is called com.ibm.ws.security.ltpa.AuthzPropTokenFactory. This token factory encodes the data in the PropagationToken and does not encrypt the data. Because the PropagationToken typically flows over Common Secure Interoperability version 2 (CSIv2) using SSL, there is no need to encrypt the token itself. However, if we need additional security for the PropagationToken, one can associate a different TokenFactory implementation with this property to get encryption. For example, if you choose to associate com.ibm.ws.security.ltpa.LTPAToken2Factory with this property, the token is AES encrypted. However, we need to weigh the performance impacts against your security needs. Adding sensitive information to the PropagationToken is a good reason to change the TokenFactory implementation to something that encrypts rather than just encodes.
If you want to perform your own signing and encryption of the default PropagationToken, implement the following classes:
- com.ibm.wsspi.security.ltpa.Token
- com.ibm.wsspi.security.ltpa.TokenFactory
Your TokenFactory implementation instantiates and validates your token implementation. We can choose to use the Lightweight Third Party Authentication (LTPA) keys passed into the initialize method of the TokenFactory or one can use your own keys. If you use your own keys, they must be the same everywhere in order to validate the tokens that are generated using those keys. See the Javadoc, available through a link on the front page of the information center, for more information on implementing your own custom TokenFactory. To associate your TokenFactory with the default PropagationToken, using the administrative console, complete the following steps:
- Click Security > Global Security.
- Under Additional properties, click Custom properties.
- Locate the com.ibm.wsspi.security.token.propagationTokenFactory property and verify that the value of this property matches your custom TokenFactory implementation.
- Verify that your implementation classes are put into the install directory/classes directory so that the WebSphere class loader can load the classes.