Security Global Forum

Security Global Forum

Our mission is to provide clients with an online user community of industry peers and IBM experts, to exchange tips and tricks, best practices, and product knowledge. We hope the information you find here helps you maximize the value of your IBM Security solutions.

 View Only

WS-Trust Clients

By Shane Weeden posted Fri July 16, 2010 12:00 AM

  

In previous postings on this blog and developerworks I’ve provided example Java code to programmatically communicate with a Security Token Service (STS) using the WS-Trust protocol. Tivoli Federated Identity Manager includes an STS that supports both WS-Trust 1.2 and WS-Trust 1.3 specifications. This posting discusses different WS-Trust Java client implementations, with a focus on moving to the WebSphere WS-Trust Client API.

Technical Overview

In my previous writings I have demonstrated two other WS-Trust clients. These are:

Both of these options support WS-Trust 1.2 only and will run on WebSphere 6.1 and later. The Higgins client requires several utility JAR files however it is portable outside of the WebSphere JRE environment. The home-grown example is smaller, but requires your own maintenance for optional WS-Trust elements that I haven’t already included in the example code.

IBM’s preferred direction is to consolidate on a single WS-Trust client that has been developed as part of the WebSphere API’s. This WS-Trust Client API is available from WebSphere version 7.0.0.7 (that’s WebSphere 7.0, fixpack 7) and later and is not available in WebSphere 6.1. There is a lot of information available about the WebSphere WS-Trust Client API in the Information Center. The goal of my post is not to repeat that information, but instead show you some specific examples of how to use the WebSphere WS-Trust client to communicate with the Tivoli Federated Identity Manager STS. I recommend you read the WebSphere Information Center reference material on the WS-Trust Client API in parallel with the rest of this article.

This post contains downloadable examples at the end which include source and provide WebSphere WS-Trust client equivalents of both the examples I have previously done with alternate STS clients.

General WebSphere Configuration

You will notice that the WebSphere WS-Trust client API is built on JAX-WS and uses a completely different configuration model for transport and message level security from JAX-RPC. Of particular interest to communicating with the TFIM STS is how we go about configuring SSL connections and optional basic-authentication support for the client. In the JAX-WS model in the J2EE container this is done external to the application code with Policy Sets and Bindings, a little like how SSL configurations can be managed outside of application code for JSSE clients.

Configuring the TFIM STS for Restricted Access

If your STS is listening on completely unprotected HTTP with no authentication requirement (on a trusted network), then no specific Poicy Set and Binding is required, however for the purposes of this demonstration my STS is only accessible via SSL, and will require basic-authentication using the user stsclient with a password. To configure this constraint on my STS I installed and deployed the TFIMRuntime on WebSphere 7, then under Applications -> Application Types -> WebSphere enterprise Applications -> ITFIM Runtime -> Security role to user/group mapping I changed the TrustClientInternalRole to just the user stsclient. This userid had to be created in the WebSphere registry. Of course group-level access control is probably more appropriate and this was just an example.

Given these contraints, we need to configure a policy set and binding to suit.

Information on configuring WebSphere policy sets and bindings for STS communications can be found here in the WebSphere Information Center and this was used as a guide for producing the instructions below.

Configuration a Policy Set for STS Communications

The policy set controls controls HTTP and SSL transport general connection parameters. Using the WebSphere console under Services -> Policy Sets -> System policy sets I created a new TFIMWSTrustPolicySet with the following resources:

  • HTTP transport
  • SSL transport

The HTTP transport resource of the policy set is configured as shown:

The SSL transport resource of the policy set is configured as shown:

Configuration a Policy Set Binding for STS Communications

The policy binding controls specific connection runtime data. In our case this is the basic-authentication username and password and the SSL certificate chain for server-authentication verification of the SSL connection. If you were using a mutually-authenticated SSL connection for the STS, it would be configured here also. Using the WebSphere console under Service -> Policy Sets -> General client policy set bindings I created a new TFIMWSTrustClient policy set binding with the following resources:

  • HTTP transport
  • SSL transport

The HTTP transport resource of the policy set binding is configured as shown. Note the inclusion of the stsuser and password for basic-authentication support:

The SSL transport resource of the policy set binding is configured as shown. Note that because my application that is acting as the WS-Trust client is actually running on the same WebSphere as the ITFIMRuntime I was able to use the NodeDefaultSSLSettings as-is. If you were running the STS on a different machine with a different SSL endpoint you would want to create your own SSL configuration settings object with the trusted certificate chain of the SSL cert at the STS.

Notes on Using the WebSphere WS-Trust Client API

Following the basic pattern shown in the WebSphere WS-Trust example at http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/rwbs_samltrustclientapi.html the WebSphere WS-Trust client API is invoked by constructing a ProviderConfig and RequesterConfig object, then obtaining an instance of WSTrustClient and calling either the issue or validate methods. Most TFIM Trust chains are best suited for use with the validate request type (and hence the validate method) as when using the TFIM STS we programattically pass a constructed initial security token and exchange it for another.

The WebSphere WS-Trust client can be used for either WS-Trust 1.2 or WS-Trust 1.3. This is controlled by the Namespace URI passed to the ProviderConfig and RequesterConfig constructors.

Similarly the SOAP version can be controlled with configuration on the RequesterConfig. TFIM expects SOAP 1.1 for WS-Trust 1.2, and SOAP 1.2 for WS-Trust 1.3.

Initialization of a ProviderConfig

Several configuration properties can be set on the ProviderConfig object. The important configuration items for communications with the TFIM STS are:

Configuration Property Description
WS-Trust Namespace URI Passed in the constructor to ProviderConfig and will be either Namespace.WST12 or Namespace.WST13
The URL to the STS Also passed in the constructor the ProviderConfig. In my test environment this is https://localhost:9443/TrustServer/SecurityTokenService (for WS-Trust 1.2) or https://localhost:9443/TrustServerWST13/services/RequestSecurityToken (for WS-Trust 1.3)
Policy Set Name Set with a call to providerConfig.setPolicySetName(“YourPolicySet”). This is only needed if you have a Policy Set such as described earlier.
Policy Set Binding Name Set with a call to providerConfig.setBindingName(“YourPolicySetBindingName”). This is only needed if you have a Policy Set Binding such as described earlier.
Policy Set Binding Scope Set with a call to providerConfig.setBindingScope(“domain”). This is only needed if you have a Policy Set Binding such as described earlier. Can be one of “domain” or “application” depending on how you configure your policy sets. There is more information on this in the WebSphere InfoCenter previous referenced.

By way of example:

  ProviderConfig providerConfig = WSSTrustClient.newProviderConfig(
    Namespace.WST13, "https://localhost:9443/TrustServerWST13/services/RequestSecurityToken");


  providerConfig.setPolicySetName("TFIMWSTrustPolicySet");
  providerConfig.setBindingName("TFIMWSTrustClient");
  providerConfig.setBindingScope("domain");  

Initialization of a RequesterConfig

Several configuration properties can also be set on the RequesterConfig object. The important configuration items for communications with the TFIM STS are:

Configuration Property Description
WS-Trust Namespace URI Passed in the constructor to RequesterConfig and will be either Namespace.WST12 or Namespace.WST13. Should match the ProviderConfig value.
Issuer Address for the RequestSecurityToken Message Optional. Set with requesterConfig.put(RequesterConfiguration.RSTT.ISSUER_ADDRESS, “http://your/issuer/address”)
AppliesTo Address for the RequestSecurityToken Message Optional. Set with requesterConfig.put(RequesterConfiguration.RSTT.APPLIESTO_ADDRESS, “http://your/appliesto/address”)
TokenType for the RequestSecurityToken Message Optional. Set with requesterConfig.put(RequesterConfiguration.RSTT.TOKENTYPE, “http://your/tokentype/URI”)
Base Token for the RequestSecurityToken Message Typically required for Validate requests. Set with requesterConfig.put(RequesterConfiguration.RSTT.VALIDATETARGET_TOKEN_XML, “<your xml token string>”)
SOAP Namespace Set with requesterConfig.setSOAPNamespace(<namespace>) where <namespace> is either Namespace.SOAP11 (for WS-Trust 1.2) or Namespace.SOAP12 (for WS-Trust 1.3)

By way of example:

  RequesterConfig requesterConfig = WSSTrustClient.newRequesterConfig(Namespace.WST13);

  // CHANGE TO SOAP11 for WS-Trust 1.2
  requesterConfig.setSOAPNamespace(Namespace.SOAP12);

  requesterConfig.put(
    RequesterConfiguration.RSTT.ISSUER_ADDRESS,
    "http://issuer/whatever");
  requesterConfig.put(
    RequesterConfiguration.RSTT.APPLIESTO_ADDRESS,
    "http://appliesto/whatever");

  // assumes stringSecurityToken is XML string
  requesterConfig.put(
    RequesterConfiguration.RSTT.VALIDATETARGET_TOKEN_XML,
    stringSecurityToken);


Initialization and use of the WS-Trust Client for Validate Requests

The WS-Trust Client object is instantiated and used as shown:

  String rstrToken = null;
  /*
   * Obtain a WS-Trust client for the provider
   */
  WSSTrustClient client = WSSTrustClient.getInstance(providerConfig);

  /*
   * Call the STS with a validate request
   */
  List validationResults = client
    .validate(providerConfig, requesterConfig);

  /*
   * Look for and process the validation results
   */
  if (validationResults != null && !validationResults.isEmpty()) {
    /*
     * There should only be one for us
     */
    WSSTrustClientValidateResult vr = validationResults.get(0);

    /*
     * Perofrm validation on the result
     */
    String statusCode = vr.getStatusCode();
    String statusReason = vr.getStatusReason();
    SecurityToken st = vr.getSecurityToken();

    String validURL_12 = "http://schemas.xmlsoap.org/ws/2005/02/trust/status/valid";
    String validURL_13 = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/status/valid";
    String validURL = validURL13; // CHANGE IF USING WS-TRUST 1.2


    if (statusCode != null && statusCode.equals(validURL)) {
      /*
       * Status is valid - now get security token as text and set
       * as result
       */
      if (st != null) {
        XMLStructure xmlStruct = st.getXML();
        if (xmlStruct != null && xmlStruct instanceof OMStructure) {
          OMStructure stOMStructure = (OMStructure) xmlStruct;
          OMElement stOMElement = stOMStructure.getNode();
          if (stOMElement != null) {
            StringWriter sw = new StringWriter();
            stOMElement.serialize(sw);
            rstrToken = sw.toString();
          } else {
            // error - STS returned a security token which did not contain a valid OMElement
          }
        } else {
          // error - STS returned a security token which is not a valid XMLStructure
        }
      } else {
        // error - STS returned a null security token
      }
    } else {
      // error - STS did not return valid status
    }
  } else {
    // error - no validation results found
  }

  // if successful, the resulting token is in rstrToken as a string

Notes on Configuring TFIM STS Chains

The WebSphere WS-Trust client API will set the RequestType element in the RequestSecurityToken message based on the WS-Trust Namespace in use, and the method called on the WSTrustClient object (validate or issue).

To ensure a correct match between client requests and the STS configuration, pay particular attention to the RequestType parameter that you select for Chain Mapping criteria when configuring a chain in the TFIM STS. If the WebSphere WS-Trust client will be used with WS-Trust 1.3 to make validate calls, then the RequestType MUST be set to Validate OASIS URI as shown here:

Similarly if you are using the WS-Trust 1.2 namespace for the WebSphere WS-Trust client, then it must be set to Validate.

Working Examples

Download 1 contains a replacement eaists.ear that uses the WebSphere WS-Trust client API to perform the same function as the download from Using Tivoli Access Manager for eBusiness WebSEAL without a user registry. This download is an EAR file. If your browser save it as a .zip file, rename it to a .ear file.

Download 2 contains a replacement STS Mapping Module that uses the WebSphere WS-Trust client API to perform the same function as the download from Complex Federation Identity and Attribute Mapping for Tivoli Federated Idenity Manager. This download is a JAR file. If your browser save it as a .zip file, rename it to a .jar file. The bundle uses a slightly different class and package name from the original as they can co-exist on the same system and I wanted to avoid naming conflicts due to the risk of stamping on existing configurations. You will need to create a new module instance and include that in your federations as the custom mapping module.

The client code is slightly different in each of the downloads as the STS Mapping Module example (Download 2) requires a class loader switch to call the WebSphere WS-Trust client in the J2EE container and outside of the TFIM OSGi runtime environment.

Use of the STS Mapping Module example also requires modification of the OSGi connector MANIFEST.MF file to include additional package exports that are not included in the shipped MANIFEST.MF. This file resides at <FIM_INSTALL_ROOT>/plugins/com.tivoli.am.fim.osgi.connector_6.2.x/META-INF/MANIFEST.MF. Updates to this file are discussed in the Advanced Development considerations of the STS Module Development Tutorial. A utility application is provided as part of the com.tivoli.am.fim.sdk downloadable package to generate the updated manifest file from the existing MANIFEST.MF deployed in the FIM plugins directory and the MANIFEST.MF contained in the com.tivoli.am.fim.demo.stsmap2_1.0.0.jar. Essentially the following 7 exported packages are required to be added to the osgi connector’s MANIFEST.MF:

  • com.ibm.websphere.wssecurity.wssapi
  • com.ibm.websphere.wssecurity.wssapi.token
  • com.ibm.wsspi.wssecurity.core.token.config
  • com.ibm.wsspi.wssecurity.trust.config
  • com.ibm.websphere.wssecurity.wssapi.trust
  • com.ibm.wsspi.wssecurity.wssapi
  • org.apache.axis2.util

Conclusion

The WebSphere WS-Trust client API is a powerful, flexible interface for calling security token services and will be the strategic direction for IBM customers that wish to invoke STS services programatically. This post demonstrates how to use the API to make validation requests to the TFIM STS, and I recommed all Tivoli Federated Identity Manager customers on WebSphere 7 who require this functionality to consider this approach rather than the legacy STS clients I have previously documented.

0 comments
6 views

Permalink