PicketLink Security Token Service

    This article presents the PicketLink Security Token Service (PicketLink STS). We start with a brief description of the WS-Trust specification. Then we present PicketLink STS and discuss its overall architecture. After that we explain how to configure and deploy the service, using an example to clarify the concepts. Finally, we show a sample client application that sends WS-Trust requests to PicketLink STS, describing the steps that need to be followed in order to get everything running with JDK 6.



    The WS-Trust specification defines extensions that build on WS-Security to provide a framework for requesting and issuing security tokens. Particularly, WS-Trust defines the concept of a security token service (STS), a service that can issue, cancel, renew and validate security tokens, and specifies the format of security token request and response messages.


    A security token request message specifies, among other things, the type of the request (issue, renew, etc), the type of the token, the lifetime of the token, information about the service provider that requested the token, and information used to encrypt the generated token. An example of a WS-Trust request message can be seen below:

    <S11:Envelope xmlns:S11=".." xmlns:wsu=".." xmlns:wst="..">
       <S11:Body wsu:Id="body">
          <wst:RequestSecurityToken Context="context">

    As we can see, the token request message is sent in the body of the SOAP message. All information related to the token request is enclosed in the RequestSecurityToken element. The sample request contains two other WS-Trust elements: RequestType, which specifies that this request is an Issue request, and TokenType, which specifies the type of the token to be issued.


    The security token response message specifies, among other things, the type of the token that has been issued, the security token itself, the lifetime of the issued token, and information that will be used by the client to decrypt the security token. An example of a token response is shown below:

    <wst:RequestSecurityTokenResponse Context="context" xmlns:wst=".." xmlns:wsu="..">
          <token:SpecialToken xmlns:token="...">

    The figure above shows a WS-Trust response message that contains a custom token. The TokenType element specifies the type of the issued token, while the RequestedSecurityToken element contains the token itself. The format of the token depends on the token type. The Lifetime element specifies when the token has been created and when it will expire.

    Web Services Trust Model

    The Web service security model defined in WS-Trust is based on a process in which a Web service can require that an incoming message prove a set of claims (e.g., name, key, permission, capability, etc.). In other words, the Web service can ask for a security token that can provide proof of such claims. A client that invokes the service without providing the token may be asked to get a token from a trusted STS first. Upon getting the token from the STS, the client retries the invocation, this time sending the obtained token in the message.


    This model is illustrated in the figure below, showing that any requestor may also be a service, and that the Security Token Service is a Web service (that is, it may express policy and require security tokens itself).




    The typical message flow is as follows:

    1. The client sends a SOAP message to the Web service.
    2. The Web service has a policy that requires a token. Upon receiving the request, the service checks if it has a security token. If the token is absent, the Web service asks the client to obtain a token from a trusted STS.
    3. The client sends a security token request message to the STS in order to obtain the token.
    4. The STS examines the request and generates the requested token, sending it back to the client.
    5. The client resends the original message to the Web service, this time including the obtained token.
    6. The Web service receives the message, extracts the token and then send a validate message to the STS in order to get the token validated.
    7. The STS validates the token ands sends a validation status back to the Web service.
    8. If the token is valid, the Web service proceed with the invocation.


    It is important to note that this is the most basic scenario in terms of trust relationships. As the STS is also a Web service, it too can have a policy that requires security tokens to be presented by clients. In this case, the client may need to obtain a different token from a second STS, and this STS may in turn require a token from a third STS and so on, creating much more complex trust relationships.

    In this section we present the PicketLink Security Token Service. As the name suggests, it is an implementation of the WS-Trust Security Token Service. The PicketLink STS does not issue tokens of a specific type. Instead, it defines generic interfaces that allows multiple token providers to be plugged in. As a result, it can be configured to deal with various types of token, as long as a token provider exists for each token type.

    Overall Architecture

    The overall architecture of the PicketLink Security Token Service is illustrated in the figure below:




    Let's give a quick description of the classes shown in the diagram:


    • PicketLinkSTS: it's the STS Web service, the component that is called by clients who want to request a security token. It implements the SecurityTokenService interface, which in turn extends the javax.xml.ws.Provider interface. The only method defined by the SecurityTokenService interface is public Source invoke(Source request). A Source object allows for generic XML source to be transmitted to the Web service - in this case, a WS-Trust request message.
    • WSTrustJAXBFactory: utility class that is used by the PicketLinkSTS to parse security token requests (i.e. convert between the XML request message and the JAXB object model) and marshall security token responses (i.e. convert the response JAXB objects to the XML response message that will be returned.
    • STSConfiguration: this object is constructed by the PicketLinkSTS and contains all the configurations defined by the STS administrator. Information like the default token timeout value, default request handler, the token provider that can handle a specific token type, are all supplied by this class. The concrete implementation is the PicketLinkSTSConfiguration.
    • WSTrustRequestHandler: instances of this interface are responsible for actually handling the WS-Trust requests. When a token request arrives, the PicketLinkSTS parses the request message and delegates the request handling to the WSTrustRequestHandler instance that has been configured. After being created, the request handler instance is given a reference to the STSConfiguration in the public void initialize(STSConfiguration config) method. It uses the configuration to find out which security token provider should be used to handle the token request and also to set the default values for properties that are absent in the WS-Trust request message.
    • WSTrustRequestContext: this class represents the security token request context. It contains all information that is relevant to the request processing. It also has a securityToken property that is used by the token providers to store the issued tokens.
    • SecurityTokenProvider: a security token provider is responsible for handling the requests for a specific token type using the information contained in the supplied WSTrustRequestContext. The token providers are plugged into the STS via configuration.


    In a nutshell, the security token request processing happens as follows:


    1. A client sends a security token request to PicketLinkSTS.
    2. PicketLinkSTS parses the request message, generating a JAXB object model.
    3. PicketLinkSTS reads the configuration file and creates the STSConfiguration object, if needed. Then it obtains a reference to the WSTrustRequestHandler from the configuration and delegates the request processing to the handler instance.
    4. The request handler uses the STSConfiguration to set default values when needed (for example, when the request doesn't specify a token lifetime value).
    5. The WSTrustRequestHandler creates the WSTrustRequestContext, setting the JAXB request object and the caller principal it received from PicketLinkSTS.
    6. The WSTrustRequestHandler uses the STSConfiguration to get the SecurityTokenProvider that must be used to process the request based on the type of the token that is being requested. Then it invokes the provider, passing the constructed WSTrustRequestContext as a parameter.
    7. The SecurityTokenProvider instance process the token request and stores the issued token in the request context.
    8. The WSTrustRequestHandler obtains the token from the context, encrypts it if needed, and constructs the WS-Trust response object containing the security token.
    9. PicketLinkSTS marshalls the response generated by the request handler and returns it to the client.


    It is important to note that many different entities can act as a PicketLink STS client. A client could be just a regular Web service client who needs to obtain or renew a security token in order to access the service, but it could also be the Web service itself trying to validate or cancel a token it has received.

    In the previous section we saw that PicketLink STS defines several interfaces that provide extension points where implementations can be plugged via configuration. We also saw that default values for some properties can be specified via configuration. This leads to a couple of questions: What configuration options are available? Where do I configure PicketLink STS?


    In this section we show how to configure PicketLink STS with the aid of an example. So we start with a sample configuration file:

    <PicketLinkSTS xmlns="urn:picketlink:identity-federation:config:1.0"
         STSName="Test STS" TokenTimeout="7200" EncryptToken="true">
         <KeyProvider ClassName="org.picketlink.identity.federation.bindings.tomcat.KeyStoreKeyManager">
              <Auth Key="KeyStoreURL" Value="keystore/sts_keystore.jks"/> 
                <Auth Key="KeyStorePass" Value="testpass"/>
                <Auth Key="SigningKeyAlias" Value="sts"/>
                <Auth Key="SigningKeyPass" Value="keypass"/>
                <ValidatingAlias Key="http://services.testcorp.org/provider1" Value="service1"/>
                <ValidatingAlias Key="http://services.testcorp.org/provider2" Value="service2"/>
              <TokenProvider ProviderClass="org.picketlink.test.identity.federation.bindings.wstrust.SpecialTokenProvider"
              <TokenProvider ProviderClass="org.picketlink.identity.federation.api.wstrust.plugins.saml.SAML20TokenProvider"
              <ServiceProvider Endpoint="http://services.testcorp.org/provider1" TokenType="http://www.tokens.org/SpecialToken"
              <ServiceProvider Endpoint="http://services.testcorp.org/provider2" TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"

    All PicketLink STS configurations must be specified in the picketlink-sts.xml file. A breakdown of the configuration elements is provided below:


    • PicketLinkSTS: the root element. It defines some properties that allows the STS administrator to set a few default values:
      • STSName: a String representing the name of the security token service. If not specified, the default PicketLinkSTS value is used.
      • TokenTimeout: the token lifetime value in seconds. If not specified, the default value of 3600 (1 hour) is used
      • EncryptToken: a boolean specifying whether issued tokens must be encrypted or not. The default value is false.
    • KeyProvider: this element and all its subelements are used to configure the keystore that will be used by PicketLink STS to sign and encrypt tokens. Properties like the keystore location, its password, and the signing (private key) alias and password are all configured in this section.
    • RequestHandler: this element specifies the fully-qualified name of the WSTrustRequestHandler implementation to be used. If not specified the default org.picketlink.identity.federation.core.wstrust.StandardRequestHandler is used.
    • TokenProviders: this section specifies the SecurityTokenProvider implementations that must be used to handle each type of security token. In the example we have two providers - one that handles tokens of type SpecialToken and one that handles tokens of type StandardToken.
    • ServiceProviders: this section specifies the token types that must be used for each service provider (the Web service that requires a security token). When a WS-Trust request doesn't contain the token type, the WSTrustRequestHandler must use the service provider endpoint to find out the type of the token that must be issued.


    Having seen the elements and what they specify, the question now is where and how is all of this used?


    • TokenTimeout is used by the WSTrustRequestHandler when no Lifetime has been specified in the WS-Trust request. It creates a Lifetime instance that has the current time as the creation time and expires after the specified number of seconds.
    • EncryptToken is used by the WSTrustRequestHandler to decide if the issued token must be encrypted or not. If true, the public key certificate (PKC) of the service provider is used to encrypt the token.
    • KeyProvider is used by the PicketLinkSTSConfiguration to access the configured keystore and provide the STS signing key (private key) and the PKCs of the service providers to the WSTrustRequestHandler when it needs to sign or encrypt a security token.
    • TokenProviders is used by the PicketLinkSTSConfiguration to obtain the SecurityTokenProvider that must be used to handle a WS-Trust request that specifies the token type. The WSTrustRequestHandler calls the getProviderForTokenType(String type)method of STSConfiguration to obtain a reference to the appropriate SecurityTokenProvider.
    • ServiceProviders is used by the PicketLinkSTSConfigurationto obtain the SecurityTokenProvider that must be used to handle a WS-Trust request that doesn't specify the token type. In this case, the request message must identify the service provider endpoint. The  PicketLinkSTSConfiguration first locates the token type of the service provider using the mappings defined in this element, and then locates the SecurityTokenProvider using the TokenProviders mappings. The WSTrustRequestHandler calls themethod of STSConfiguration to obtain a reference to the appropriate SecurityTokenProvider.


    NOTE 1: in this text, a service provider refers to the Web service that requires a security token to be presented by its clients.

    NOTE 2: the example shows a configuration example that defines providers for custom token types (such as SpecialToken). For a list of standard token types, see the token profiles specified by OASIS.

    In this section we cover the steps needed to package, secure and deploy PicketLink STS. As a simple class that has been annotated with @WebServiceProvider, PicketLinkSTS needs to be packaged in a war file. The structure of this file looks like this:



    • WEB-INF/
      • classes/
        • com/mycompany/myproviders/
        • picketlink-sts.xml
      • lib/
        • picketlink-fed.jar
      • wsdl/
        • PicketLinkSTS.wsdl
      • web.xml
      • jboss-web.xml
      • jboss-wsse-server.xml


    A quick explanation of the WAR structure:

    • WEB-INF/classes contains your custom security token providers and other classes you need to plug into PicketLink STS, as well as the picketlink-sts.xml configuration file, which was covered in the previous section.
    • WEB-INF/lib contains the library that implements the PicketLink Security Token Service: picketlink-fed.jar.
    • WEB-INF/wsdl contains the PicketLinkSTS.wsdl file. An example of WSDL can be seen in the figure below:
    <?xml version="1.0"?>
    <wsdl:definitions name="PicketLinkSTS" targetNamespace="urn:picketlink:identity-federation:sts"
        <xs:schema targetNamespace="urn:picketlink:identity-federation:sts" 
          <xs:complexType name="MessageBody">
                <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##any"/>
      <wsdl:message name="RequestSecurityToken">
        <wsdl:part name="rstMessage" element="tns:MessageBody"/>
      <wsdl:message name="RequestSecurityTokenResponse">
        <wsdl:part name="rstrMessage" element="tns:MessageBody"/>
      <wsdl:portType name="SecureTokenService">
        <wsdl:operation name="IssueToken">
          <wsdl:input wsap10:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue" message="tns:RequestSecurityToken"/>
          <wsdl:output wsap10:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Issue" message="tns:RequestSecurityTokenResponse"/>
      <wsdl:binding name="STSBinding" type="tns:SecureTokenService">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="IssueToken">
          <soap12:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue" style="document"/>
            <soap12:body use="literal"/>
            <soap12:body use="literal"/>
      <wsdl:service name="PicketLinkSTS">
        <wsdl:port name="PicketLinkSTSPort" binding="tns:STSBinding">
          <soap12:address location="http://localhost:8080/picketlink-sts"/>

    PicketLink STS requires that the service name and port are called PicketLinkSTS and PicketLinkSTSPort, respectively. You can, however, change the SOAP address to better reflect your target deployment environment.

    • WEB-INF/web.xml is where you configure the servlet that will receive the SOAP requests. It looks like the following:
    <?xml version="1.0"?>
    <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

    Notice that we have protected the STS using the role JBossAdmin. This means that only callers in this role will be allowed to make a WS-Trust request to PicketLink STS.

    • WEB-INF/jboss-web.xml is where we configure the JBoss security domain that must be used to authenticate and authorize callers:
    <?xml version="1.0" encoding="UTF-8"?>

    This example tells JBoss Application Server that it should use the PicketLinkSTS domain to authenticate and authorize users. For this to work, a PicketLinkSTS domain must be configured in the Application Server. For more information about security configuration, see the this document.

    • WEB-INF/jboss-wsse-server.xml is the file where the Username Token Profile is configured for PicketLink STS. When sending a request, the client username and password are sent along with the SOAP message using the OASIS Username Token Profile. This file tells JBossWS that it should obtain the username and password from the SOAP header specified by the Username Token Profile.


    After configuring all required files, we can proceed to the WAR creation. This is done by executing the comand

    $jar cf picketlink-sts.war WEB-INF

    This will create the picketlink-sts.war file that can be deployed on JBoss AS. This is accomplished by copying the picketlink-sts.war file to $JBOSS_HOME/server/default/deploy.


    NOTE: the STS has been tested on JBoss AS 5.1.0.GA-JDK6 and on JBoss AS 6.0.0.Mx. If you are not using one of these versions you may need to install JBossWS and copy some jars to $JBOSS_HOME/lib/endorsed so that the JAXWS classes from JBossWS don't conflict with the JDK 6 classes. Instructions can be found here.


    After deploying the picketlink-sts.war file, start the application server. You should see the log messages informing you that the service has been correctly deployed:

    15:09:30,724 INFO  [DefaultEndpointRegistry] register: jboss.ws:context=picketlink-sts,endpoint=PicketLinkSTS
    15:09:30,944 INFO  [TomcatDeployment] deploy, ctxPath=/picketlink-sts
    15:09:31,468 INFO  [WSDLFilePublisher] WSDL published to: file:/opt/jboss-5.1.0.GA/server/default/data/wsdl/picketlink-sts.war/PicketLinkSTS.wsdl


    The deployable picketlink-sts.war can be found attached below.

    Sample Client Application

    In this section we show an example of a client application that invokes PicketLink STS to get a custom token. The process basically involves calling the WSTrustClient API:


     * JBoss, Home of Professional Open Source Copyright 2009, Red Hat Middleware
     * LLC, and individual contributors by the @authors tag. See the copyright.txt
     * in the distribution for a full listing of individual contributors.
     * This is free software; you can redistribute it and/or modify it under the
     * terms of the GNU Lesser General Public License as published by the Free
     * Software Foundation; either version 2.1 of the License, or (at your option)
     * any later version.
     * This software is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
     * details.
     * You should have received a copy of the GNU Lesser General Public License
     * along with this software; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
     * site: http://www.fsf.org.
    package test;
    import javax.xml.transform.Result;
    import javax.xml.transform.Source;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import org.picketlink.identity.federation.api.wstrust.WSTrustClient;
    import org.picketlink.identity.federation.api.wstrust.WSTrustClient.SecurityInfo;
    import org.picketlink.identity.federation.core.wstrust.WSTrustException;
    import org.picketlink.identity.federation.core.wstrust.plugins.saml.SAMLUtil;
    import org.w3c.dom.Element;
     * <p>
     * This class shows how to use the {@code WSTrustClient} API to obtain and validate tokens with the PicketLink STS.
     * </p>
     * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
    public class WSTrustClientTest
       public static void main(String[] args) throws Exception
          new WSTrustClientTest().testSTS();
       public void testSTS() throws Exception
          // create a WSTrustClient instance.
          WSTrustClient client = new WSTrustClient("PicketLinkSTS", "PicketLinkSTSPort", 
                new SecurityInfo("admin", "admin"));
          // issue a SAML assertion using the client API.
          Element assertion = null;
             assertion = client.issueToken(SAMLUtil.SAML2_TOKEN_TYPE);
          catch (WSTrustException wse)
             System.out.println("Unable to issue assertion: " + wse.getMessage());
          // print the assertion for demonstration purposes.
          System.out.println("\nSuccessfully issued a standard SAMLV2.0 Assertion!");
          // validate the received SAML assertion.
             System.out.println("\n\nIs assertion valid? " + client.validateToken(assertion));
          catch (WSTrustException wse)
             System.out.println("\n\nFailed to validate SAMLV2.0 Assertion: " + wse.getMessage());
       private void printAssertion(Element assertion) throws Exception
          TransformerFactory tranFactory = TransformerFactory.newInstance();
          Transformer aTransformer = tranFactory.newTransformer();
          Source src = new DOMSource(assertion);
          Result dest = new StreamResult(System.out);
          aTransformer.transform(src, dest);

    As the code shows, the first step is to create an instance of WSTrustClient. The constructor takes several arguments: the STS service name, STS service port, STS URL, and a SecurityInfo object that contains the username and password of the user invoking the STS.


    Once we have an instance of WSTrustClient we can invoke the issueToken method, specifying the type of token that is to be issued. A WS-Trust request is created and marshalled into a SOAP message. The SOAP message contains a UsernameToken in the security header that will carry the specified username/password. After dispatching the message to the STS, the WSTrustClient parses the response and returns the issued token element.


    Upon receiving the issued assertion, we print it using a Transformer. Then we use the API to validate the assertion by calling the validateToken method. This method returns a boolean indicating whether the assertion has been considered valid or not.


    The output of the sample client application looks like the following:

    Successfully issued a standard SAMLV2.0 Assertion!
    <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="ID-fca1fdb2-85aa-41aa-9d72-f0eff8bb1970" IssueInstant="2009-05-31T22:49:20.294Z"><saml2:Issuer>PicketLinkSTS</saml2:Issuer><saml2:Subject><saml2:NameID NameQualifier="urn:picketlink:identity-federation">admin</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"/></saml2:Subject><saml2:Conditions NotBefore="2009-05-31T22:49:20.294Z" NotOnOrAfter="2009-06-01T00:49:20.294Z"/><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#ID-fca1fdb2-85aa-41aa-9d72-f0eff8bb1970"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>y2XRxnPqRJHxbpYsO0m/AWlRSVA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>LJDp0k8Hm6JM94bDLFpGynr525N/UmGNrnWaKpLchdq3hV9wmo328lGGo3LzTo6k/UUa7T6J+z0q
    Is assertion valid? true


    NOTE 1: The sample assumes that an admin with password admin exists in the application server security domain. Make sure to change this to reflect the users that exist in your test environment.

    NOTE 2: The sample application just needs pickelink-fed.jar in the classpath to run with JDK6. However, if you wish to use JBossWS to dispatch the request message, you need to add jbossws-native-client.jar (found in $JBOSS_HOME/client) to the classpath and also point to the application server endorsed dir to avoid conflicts between JBossWS and JDK implementations:

    $ java test.WSTrustClientTest -Djava.endorsed.dirs=$JBOSS_HOME/lib/endorsed -cp CLASSPATH


    Troubleshooting Problems

    1. Ensure that you have followed the endorsed mechanism above (Including the JBossWS installation). 
    2. Ask questions in the PicketLink user forum.  Be patient. You cannot expect an answer right away.