9.2. STS Demonstration
9.2.1. Overview of the Demonstration
Overview
The standalone Apache CXF distribution includes an STS demonstration in the following location:
CXFInstallDir/samples/sts
This demonstration illustrates a complete Holder-of-Key scenario, including all of the code for the client, server, and standalone STS.
The demonstration scenario
Figure 9.5, “STS Demonstration Scenario” shows an overview of the STS demonstration scenario and the steps required to implement single-sign on in the context of WS-Trust and the STS.
Figure 9.5. STS Demonstration Scenario
In this Holder-of-Key scenario, there are two main stages involved in invoking an operation on the server: first the client obtains a single-sign on token (SAML token) from the STS; then the client invokes the WSDL operation on the server, embedding the SAML token in the SOAP security header.
The client-STS connection
The client-STS connection is used to obtain the single-sign on token (SAML token) from the STS. This connection is secured by a symmetric binding (for message protection) and messages must include a UsernameToken (for client authentication).
The symmetric binding is characterized by the fact that only one key pair is required (the STS X.509 certificate and private key) and the symmetric session key is derived from this key pair. To support the symmetric binding, the client must be configured with the STS X.509 certificate (public key) and the STS must be configured with the corresponding STS private key.
The UsernameToken credentials, which must accompany the Issue request sent to the STS, are used to authenticate the client.
The client-server connection
The client-server connection is established after the client has obtained the single-sign on token from the STS and is used to invoke the
greetMe
WSDL operation. This connection is secured by an asymmetric binding (for message protection and authentication).
The asymmetric binding is characterized by the fact that two key pairs are required: the Initiator token (a SAML token containing the client X.509 certificate); and the Recipient token (server X.509 certificate and private key). Both the client key pair and the server key pair are used for message protection.
The SAML token sent by the client contains a copy of the client's X.509 certificate and is used to authenticate the client (in a Holder-of-Key scenario).
Invocation steps
In the STS demonstration scenario shown in Figure 9.5, “STS Demonstration Scenario”, the client makes a secure invocation on the server as follows:
- The secure invocation is initiated when the client calls the
greetMe()
method. - Before sending a request message to the server, the client must ask the STS to issue the token that will be used for single sign-on. The client delegates this task to the
STSClient
bean, which is itself a fully-fledged WS client that can communicate with the STS.To establish the connection to the STS, theSTSClient
bean must initialize a symmetric binding, as follows:- The
STSClient
generates an ephemeral key (the symmetric session key). - The
STSClient
encrypts the ephemeral key using the STS public key (X.509 certificate). - The ephemeral key is then used for signing and encrypting the SOAP message parts sent between the
STSClient
bean and the STS.
- The
STSClient
bean now constructs the RequestSecurityToken (RST) message, which it sends to the STS. TheSTSClient
embeds the client's X.509 certificate (to be used as the client's identity in the Holder-of-Key scenario) and the client's UsernameToken credentials (UT) into the RST message.TheSTSClient
bean now uses the RST message to invoke the STS Issue operation. - When the RST message arrives in the STS, the STS endpoint immediately tries to authenticate the embedded UsernameToken credentials. If the UsernameToken credentials could not be authenticated, the message would be rejected.
- The STS now processes the issue token request. The RST asks the STS to generate a SAML token, using the client's X.509 certificate as the Holder-of-Key identity. The STS constructs a RequestSecurityTokenResponse (RSTR) message containing a SAML token, taking care to sign the generated SAML token using the STS signing key.
- The STS returns the RSTR message containing the signed SAML token.
- The client is now ready to send the
greetMe
request to the server. The signed SAML token that was issued by the STS is embedded in the SOAP security header of the request message. - The first thing that the server does is to check that the SAML token is signed by the STS public key. To be more precise, what the server actually does is to check whether the SAML token is signed by any trusted key—that is, any of the public keys that can be found in the
servicestore.jks
keystore file.If the SAML token is not signed by a trusted key, the message is rejected, because it is then impossible to establish trust in the SAML token. - The server now performs the Holder-of-Key check, to establish the client's identity (effectively, authenticating the client).The X.509 certificate embedded in the SAML token is meant to be the client identity, but the client must also prove that it possesses the corresponding private key for the certificate, in order to be authentic. It turns out that, as part of the natural configuration of the asymmetric binding policy, the client is configured to sign various parts of the SOAP message using the
myclientkey
private key. The server therefore checks all of the message's signing keys and if it finds one that matches the X.509 certificate in the SAML token, it knows that the client is in possession of the private key. - If all of the security checks have been successful, the server now invokes the implementation of the
greetMe
WSDL operation.
Single-sign on and scalability
Notice that the client in this scenario is required to hold a copy of the server's X.509 certificate (
myservicekey
certificate). The server's certificate must be distributed to the clients using some out-of-band approach, which creates some extra work when scaling up to a large system.
On the other hand, the server requires absolutely no knowledge whatsoever about the client. It relies entirely on the STS to establish trust with a client. This is a great advantage for scalability of the system.
9.2.2. STS WSDL Contract
Overview
The STS WSDL contract specifies the address used to contact the STS and the STS WSDL also specifies the kind of security that applies to incoming connections. In the current demonstration, the STS requires clients to support the symmetric binding and to authenticate by providing UsernameToken credentials.
Location of the STS WSDL contract
The STS WSDL contract can be found in the following location:
CXFInstallDir/samples/sts/wsdl/ws-trust-1.4-service.wsdl
Parts of the contract
The most important parts of the STS WSDL contract are, as follows:
- STS port type—the standard WSDL port type for the STS, as defined the WS-Trust specification.NoteThere are some other standard WSDL port types defined in the WSDL file, but these port types are not used in this demonstration.
- WSDL binding—the SOAP binding for the STS port type. Policies are enabled by applying them to various parts of the WSDL binding.
- WSDL service and port—the WSDL port element specifies the address of the STS Web service endpoint.
- Binding policy—a WS-Policy element that specifies how connections to the STS must be secured.
- Signed/encrypted parts policies—a WS-Policy element for input messages and a WS-Policy element for output messages, specifying which parts of the incoming SOAP messages and the outgoing SOAP messages must be signed and encrypted.
STS port type
The STS port type provides an abstract description of all the WSDL operations supported by the STS. The STS port type appearing the STS WSDL file is taken directly from the WS-Trust specification. Only the Issue operation is actually implemented in this demonstration, however.
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:tns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:wstrust="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsap10="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" > ... <!-- This portType is an example of an STS supporting full protocol --> <wsdl:portType name="STS"> <wsdl:operation name="Cancel"> ... </wsdl:operation> <wsdl:operation name="Issue"> ... </wsdl:operation> <wsdl:operation name="Renew"> ... </wsdl:operation> <wsdl:operation name="Validate"> ... </wsdl:operation> <wsdl:operation name="KeyExchangeToken"> ... </wsdl:operation> <wsdl:operation name="RequestCollection"> ... </wsdl:operation> </wsdl:portType> ... </wsdl:definitions>
WSDL binding
The WSDL binding for the STS is a regular SOAP binding (as could be generated using the Apache CXF
wsdl2soap
utility), except for the wsp:PolicyReference
elements, which are used to apply the relevant security policies to the binding. Hence, the policy identified by UT_policy
is applied to the whole binding and the Input_policy
and the Output_policy
are applied respectively to the input messages and the output messages of each operation.
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsdl:binding name="UT_Binding" type="wstrust:STS"> <wsp:PolicyReference URI="#UT_policy" /> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="Issue"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue" /> <wsdl:input> <wsp:PolicyReference URI="#Input_policy" /> <soap:body use="literal" /> </wsdl:input> <wsdl:output> <wsp:PolicyReference URI="#Output_policy" /> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="Validate"> ... </wsdl:operation> <wsdl:operation name="Cancel"> ... </wsdl:operation> <wsdl:operation name="Renew"> ... </wsdl:operation> <wsdl:operation name="KeyExchangeToken"> ... </wsdl:operation> <wsdl:operation name="RequestCollection"> ... </wsdl:operation> </wsdl:binding> ... </wsdl:definitions>
For full details of how policy references work, see Policies and policy references.
WSDL service and port
The WSDL service and WSDL port elements are used to define the address of the STS endpoint (specified by the
location
attribute of soap:address
).
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ... >
...
<wsdl:service name="SecurityTokenService">
<wsdl:port name="UT_Port" binding="tns:UT_Binding">
<soap:address location="http://localhost:8080/SecurityTokenService/UT" />
</wsdl:port>
</wsdl:service>
...
</wsdl:definitions>
Binding policy
The binding policy,
UT_policy
, defines what kind of security is applied to incoming STS connections.
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsp:Policy wsu:Id="UT_policy"> <wsp:ExactlyOne> <wsp:All> <wsap10:UsingAddressing/> <sp:SymmetricBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"> <wsp:Policy> <sp:RequireDerivedKeys /> <sp:RequireThumbprintReference /> <sp:WssX509V3Token10 /> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128 /> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax /> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp /> <sp:EncryptSignature /> <sp:OnlySignEntireHeadersAndBody /> </wsp:Policy> </sp:SymmetricBinding> <sp:SignedSupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssUsernameToken10 /> </wsp:Policy> </sp:UsernameToken> </wsp:Policy> </sp:SignedSupportingTokens> <sp:Wss11 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier /> <sp:MustSupportRefIssuerSerial /> <sp:MustSupportRefThumbprint /> <sp:MustSupportRefEncryptedKey /> </wsp:Policy> </sp:Wss11> <sp:Trust13 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:MustSupportIssuedTokens /> <sp:RequireClientEntropy /> <sp:RequireServerEntropy /> </wsp:Policy> </sp:Trust13> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... </wsdl:definitions>
The binding policy defines the STS security policy to be a symmetric binding. This implies that security is applied at the SOAP message level, where parts of the SOAP payload are liable to be encrypted and/or signed. Because this is a symmetric binding, the keys used for encrypting and signing in both directions are derived from a single key, specified by the
sp:ProtectionToken
element (which is ultimately configured to be the mystskey
private key and X.509 certificate on the STS server). The client is required to include a WSS UsernameToken in the SOAP security header, which is used by the STS to authenticate the client.
For a more detailed discussion of the symmetric binding policy, see
.
Signed parts and encrypted parts policies
The
Input_policy
policy is used to specify exactly which parts of an input message should be encrypted and/or signed by the symmetric session keys. In addition to signing and encrypting the SOAP body, the standard WS-Addressing SOAP headers are also signed (which protects them from tampering by third-parties).
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ... >
...
<wsp:Policy wsu:Id="Input_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
...
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
...
</wsdl:definitions>
The
Output_policy
policy is used to specify exactly which parts of an output message should be encrypted and/or signed by the symmetric session keys.
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ... >
...
<wsp:Policy wsu:Id="Output_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
<sp:Header ... />
...
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
...
</wsdl:definitions>
9.2.3. Security Token Service Configuration
Overview
Figure 9.6, “Demonstration STS Configuration” shows an overview of how the STS is configured for the current demonstration.
Figure 9.6. Demonstration STS Configuration
Aspects of configuration
The current demonstration configures the following aspects of the STS:
- WSDL contract and security policies—as already discussed in Section 9.2.2, “STS WSDL Contract”, the policies in the WSDL contract are used to define the type of security that protects incoming connections to the STS. In particular, it is important that some form of client authentication is required by these security policies.
- STS plug-in configuration—as described in Section 9.1.1, “Overview of the STS”, the STS has a plug-in architecture. In order to instantiate an STS server, you must assemble and configure the STS plug-ins that you want to use.
- STS signing key—you must configure the STS with its own signing key, which effectively provides the stamp of authenticity for any tokens issued by the STS.
- List of known Web service endpoints—you can optionally install a service plug-in into the STS, which is used to define a list of known Web service endpoints that can use the STS (see Section 9.4, “Enabling AppliesTo in the STS”).
- JAX-WS endpoint configuration—you must define a Web service endpoint for the STS, which clients use to connect to the STS. In the JAX-WS endpoint you specify the X.509 certificate and private key that are used as the protection token in the symmetric binding and you also specify a callback handler, that accesses the database of UsernameToken credentials for authenticating clients.
Location of the STS Spring configuration
The STS Spring configuration file can be found in the following location:
CXFInstallDir/samples/sts/src/main/resources/wssec-sts.xml
STS plug-in configuration
The first part of the
wssec-sts.xml
Spring configuration file is concerned with instantiating the STS implementation and specifying the relevant STS plug-ins to use:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:test="http://apache.org/hello_world_soap_http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd"> ... <bean id="utSTSProviderBean" class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider"> <property name="issueOperation" ref="utIssueDelegate"/> <property name="validateOperation" ref="utValidateDelegate"/> </bean> <bean id="utIssueDelegate" class="org.apache.cxf.sts.operation.TokenIssueOperation"> <property name="tokenProviders" ref="utSamlTokenProvider"/> <property name="services" ref="utService"/> <property name="stsProperties" ref="utSTSProperties"/> </bean> <bean id="utValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation"> <property name="tokenValidators" ref="utSamlTokenValidator"/> <property name="stsProperties" ref="utSTSProperties"/> </bean> <bean id="utSamlTokenProvider" class="org.apache.cxf.sts.token.provider.SAMLTokenProvider"> </bean> <bean id="utSamlTokenValidator" class="org.apache.cxf.sts.token.validator.SAMLTokenValidator"> </bean> ... </beans>
In the demonstration STS instance, only two STS operations are supported: Issue, implemented by the
utIssueDelegate
bean, and Validate, implemented by the utValidateDelegate
bean. The Validate operation is not used in the current demonstration.
The
utIssueDelegate
bean is configured with the following properties:
tokenProviders
- A list of plug-ins that can generate various kinds of token. In this demonstration, this list is initialized with a single provider,
SAMLTokenProvider
, which is capable of generating SAML tokens. services
- (Optional) The
services
property enables you to specify the Web services that are secured by the STS, by specifying a list of regular expressions that must match the Web service URLs. stsProperties
- The
stsProperties
specifies some generic configuration settings that are common to many of the plug-ins in the STS.
STS signing key
The STS signing key—which is used to sign all of the tokens issued by the STS—is specified by setting the following properties on the
StaticSTSProperties
class:
signaturePropertiesFile
- A WSS4J properties file that defines the properties for accessing the
keys/stsstore.jks
Java keystore file. signatureUsername
- The alias of the STS signing key in the Java keystore file.
callbackHandlerClass
- A callback handler class that returns the password for accessing the STS signing key.
The
StaticSTSProperties
class is instantiated as the utSTSProperties
bean in the wssec-sts.xml
configuration file:
<beans ... > ... <bean id="utSTSProperties" class="org.apache.cxf.sts.StaticSTSProperties"> <property name="signaturePropertiesFile" value="stsKeystore.properties"/> <property name="signatureUsername" value="mystskey"/> <property name="callbackHandlerClass" value="demo.wssec.sts.STSCallbackHandler"/> <property name="issuer" value="DoubleItSTSIssuer"/> </bean> ... </beans>
List of known Web service endpoints
The
utService
bean enables you to specify the Web service endpoints that are known to the STS, as follows:
<beans ... >
...
<bean id="utService"
class="org.apache.cxf.sts.service.StaticService">
<property name="endpoints" ref="utEndpoints"/>
</bean>
<util:list id="utEndpoints">
<value>http://localhost:(\d)*/SoapContext/SoapPort</value>
</util:list>
...
</beans>
The
utEndpoints
bean instantiates a java.util.List
object containing a list of regular expressions that must match the server's endpoint URL. When a client requests a new token from the STS, it includes the server's endpoint URL in the request, so that the STS can check whether or not the target endpoint is a known endpoint.
For more details about how to configure this, see Section 9.4, “Enabling AppliesTo in the STS”.
JAX-WS endpoint configuration
To create a HTTP/SOAP endpoint that listens for incoming connections to the STS, define a
jaxws:element
, as follows:
<beans ... > ... <jaxws:endpoint id="UTSTS" implementor="#utSTSProviderBean" address="http://localhost:8080/SecurityTokenService/UT" wsdlLocation="wsdl/ws-trust-1.4-service.wsdl" xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" serviceName="ns1:SecurityTokenService" endpointName="ns1:UT_Port"> <jaxws:properties> <entry key="security.callback-handler" value="demo.wssec.sts.STSCallbackHandler"/> <entry key="security.signature.properties" value="stsKeystore.properties"/> <entry key="security.signature.username" value="mystskey"/> </jaxws:properties> </jaxws:endpoint> ... </beans>
In addition to the usual attributes required for a JAX-WS endpoint, the
jaxws:endpoint
element defines properties for accessing the protection token and a reference to a callback handler instance.
Protection token for the symmetric binding
The protection token provides the fundamental basis for the symmetric binding. It is used to generate all of the sessions keys for the connection. Although you might expect the corresponding properties to be called something like protection.token, the following properties of
jaxws:endpoint
are, in fact, used to specify the protection token:
security.signature.properties
- A WSS4J properties file that defines the properties for accessing the
keys/stsstore.jks
Java keystore file. security.signature.username
- The alias of the protection token (X.509 certificate and private key pair) in the Java keystore file.
security.callback-handler
- A callback handler class that returns the password for accessing the protection token.
It so happens that in this demonstration, the protection token uses the same X.509 certificate and private key as the STS signing key.
STS callback handler
The
jaxws:endpoint
element is also configured with a callback handler (through the security.callback-handler
property), as follows:
// Java package demo.wssec.sts; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class STSCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof WSPasswordCallback) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; if ("mystskey".equals(pc.getIdentifier())) { pc.setPassword("stskpass"); break; } else if ("alice".equals(pc.getIdentifier())) { pc.setPassword("clarinet"); break; } } } } }
The security callback handler can be used for multiple purposes (for example, see Providing Client Credentials). In particular, in this demonstration the callback handler on the
jaxws:element
is used for the following purposes:
- Retrieving the password for the protection tokenthe protection token consists of a private key/public key pair and a password is needed to access the private key (which is stored in a Java keystore file).
- Retrieving the password for a client's UsernameToken credentialsthe symmetric binding policy in this demonstration requires the client to send UsernameToken credentials to the STS, for the purpose of authenticating the client. The callback handler must therefore have access to a database of UsernameToken credentials, in order to authenticate the incoming UsernameToken credentials. In this example, just a single UsernameToken credential is supported, with username,
alice
, and password,clarinet
.NoteIn an enterprise security system, it is more likely that you would use an LDAP server to store the client UsernameToken credentials.
9.2.4. Server WSDL Contract
Overview
The server WSDL contract determines the kind of security policies that are applied to the client-server connection. In the current demonstration, this connection is secured by an asymmetric binding policy.
A particularly important aspect of this policy is that the
InitiatorToken
is specified by an IssuedToken
policy element. It is the presence of the IssuedToken
element in the policy which triggers the client to call out to the STS, requesting the STS to issue a SAML token for single sign-on.
Location of the server WSDL contract
The server WSDL contract can be found in the following location:
CXFInstallDir/samples/sts/wsdl/hello_world.wsdl
Parts of the contract
The most important parts of the server WSDL contract are, as follows:
- Greeter port type—a simple hello world interface consisting of a single WSDL operation,
greetMe
. - WSDL binding—the SOAP binding for the
Greeter
port type. Policies are enabled by applying them to various parts of the WSDL binding. - WSDL service and port—the WSDL port element specifies the address of the
Greeter
Web service endpoint. - Binding policy—a WS-Policy element that specifies how connections to the server must be secured.
- Signed/encrypted parts policies—a WS-Policy element for input messages and a WS-Policy element for output messages, specifying which parts of the incoming SOAP messages and the outgoing SOAP messages must be signed and encrypted.
Greeter port type
The
Greeter
port type defines the logical interface to the Web service provided by the server, as follows:
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://apache.org/hello_world_soap_http" xmlns:x1="http://apache.org/hello_world_soap_http/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:wsaw="http://www.w3.org/2005/08/addressing" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> ... <wsdl:portType name="Greeter"> <wsdl:operation name="greetMe"> <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/> <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/> </wsdl:operation> </wsdl:portType> ... </wsdl:definitions>
Binding
The WSDL binding for the
Greeter
port type is a regular SOAP binding, except for the wsp:PolicyReference
elements, which are used to apply the relevant security policies to the binding. Hence, the policy identified by AsymmetricSAML2Policy
is applied to the whole binding and the Input_policy
and the Output_policy
are applied respectively to the input messages and the output messages of each operation.
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <wsp:PolicyReference URI="#AsymmetricSAML2Policy" /> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="greetMe"> <soap:operation soapAction="" style="document"/> <wsdl:input name="greetMeRequest"> <soap:body use="literal"/> <wsp:PolicyReference URI="#Input_Policy" /> </wsdl:input> <wsdl:output name="greetMeResponse"> <soap:body use="literal"/> <wsp:PolicyReference URI="#Output_Policy" /> </wsdl:output> </wsdl:operation> </wsdl:binding> ... </wsdl:definitions>
For full details of how policy references work, see Policies and policy references.
Service and port
The WSDL service and WSDL port elements are used to define the address of the
Greeter
WS endpoint (specified by the location
attribute of soap:address
).
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ... >
...
<wsdl:service name="SOAPService">
<wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
<soap:address location="http://localhost:9001/SoapContext/SoapPort"/>
</wsdl:port>
</wsdl:service>
...
</wsdl:definitions>
Binding policy
The binding policy,
AsymmetricSAML2Policy
, defines what kind of security is applied to incoming server connections.
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsp:Policy wsu:Id="AsymmetricSAML2Policy"> <wsp:ExactlyOne> <wsp:All> <wsam:Addressing wsp:Optional="false"> <wsp:Policy /> </wsam:Addressing> <sp:AsymmetricBinding> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:IssuedToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <sp:RequestSecurityTokenTemplate> <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType> <t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey</t:KeyType> </sp:RequestSecurityTokenTemplate> <wsp:Policy> <sp:RequireInternalReference /> </wsp:Policy> <sp:Issuer> <wsaw:Address>http://localhost:8080/SecurityTokenService/ </wsaw:Address> </sp:Issuer> </sp:IssuedToken> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"> <wsp:Policy> <sp:WssX509V3Token10 /> <sp:RequireIssuerSerialReference /> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:Layout> <wsp:Policy> <sp:Lax /> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp /> <sp:OnlySignEntireHeadersAndBody /> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic128 /> </wsp:Policy> </sp:AlgorithmSuite> </wsp:Policy> </sp:AsymmetricBinding> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefIssuerSerial /> <sp:MustSupportRefThumbprint /> <sp:MustSupportRefEncryptedKey /> </wsp:Policy> </sp:Wss11> <sp:Trust13> <wsp:Policy> <sp:MustSupportIssuedTokens /> <sp:RequireClientEntropy /> <sp:RequireServerEntropy /> </wsp:Policy> </sp:Trust13> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... </wsdl:definitions>
The binding policy defines the
Greeter
server security policy to be an asymmetric binding. This implies that security is applied at the SOAP message level, where parts of the SOAP payload are liable to be encrypted and/or signed. Because this is an asymmetric binding, two keys must be provided:
- Initiator token—a SAML token, which has the client's X.509 certificate embedded inside it. Because the initiator token is defined to be an
IssuedToken
token, it is actually obtained by the querying the STS (using anSTSClient
object). - Recipient token—an X.509 certificate (public key) and private key pair, which is provided by the server side.
For a more detailed discussion of the asymmetric binding policy, see
.
IssuedToken policy
Take a closer look at the
IssuedToken
policy, which is the IntiatorToken in the server's asymmetric binding. It is defined as follows:
<sp:IssuedToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <sp:RequestSecurityTokenTemplate> <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType> <t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey</t:KeyType> </sp:RequestSecurityTokenTemplate> <wsp:Policy> <sp:RequireInternalReference /> </wsp:Policy> <sp:Issuer> <wsaw:Address>http://localhost:8080/SecurityTokenService/</wsaw:Address> </sp:Issuer> </sp:IssuedToken>
The
IssuedToken
policy is the key component of WS-Trust. It triggers the client to request an issued token from the STS. The sp:RequestSecurityTokenTemplate
element specifies some elements that are to be included in the request that is sent to the STS. It includes the following elements:
<t:TokenType>...#SAMLV2.0</t:TokenType>
- Indicates that the client wishes the STS to issue a SAML 2.0 token.
<t:KeyType>.../PublicKey</t:KeyType>
- Indicates that the client wants the STS to support the Holder-of-Key scenario, where an X.509 certificate (public key) is used to verify the client identity. This implies that the client's X.509 certificate will be included in the request sent to the STS.
Signed parts and encrypted parts policies
The
Input_policy
policy is used to specify exactly which parts of an input message should be encrypted and/or signed by the asymmetric session keys (initiator token and recipient token). In addition to signing and encrypting the SOAP body, the standard WS-Addressing SOAP headers are also signed (which protects them from tampering by third-parties).
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsp:Policy wsu:Id="Input_Policy"> <wsp:ExactlyOne> <wsp:All> <sp:EncryptedParts> <sp:Body /> </sp:EncryptedParts> <sp:SignedParts> <sp:Body /> <sp:Header ... /> ... </sp:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... </wsdl:definitions>
The
Output_policy
policy is used to specify exactly which parts of an output message should be encrypted and/or signed by the asymmetric session keys (initiator token and recipient token).
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ... > ... <wsp:Policy wsu:Id="Output_Policy"> <wsp:ExactlyOne> <wsp:All> <sp:EncryptedParts> <sp:Body /> </sp:EncryptedParts> <sp:SignedParts> <sp:Body /> <sp:Header ... /> ... </sp:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... </wsdl:definitions>
9.2.5. Server Configuration
Overview
Figure 9.7, “Demonstration Server Configuration” shows an overview of the configuration for the demonstration server.
Figure 9.7. Demonstration Server Configuration
Aspects of configuration
The most important aspects of the server configuration are, as follows:
- WSDL contract and security policies—as already discussed in Section 9.2.4, “Server WSDL Contract”, the policies in the WSDL contract are used to define the type of security that protects incoming connections to the
Greeter
server. - JAX-WS endpoint configuration—in the JAX-WS endpoint you specify the X.509 certificate and private key that are used as the recipient token in the asymmetric binding and you also specify the certificate (or certificates) for checking the signature of a SAML token.
- Recipient token—is specified by setting the relevant properties in the JAX-WS endpoint configuration.
- Server-side SAML token interceptor—the SAML token interceptor checks the signature of the SAML token, using the X.509 certificates (public keys) stored in the keystore file referenced by the
security.encryption.properties
property. - Server callback handler—is used to provide the passwords for private keys.
- Related STS configuration—when setting up a new server, you must remember to add an appropriate regular expression to the list of known Web service endpoints in the STS, or the STS will refuse to perform any operations for this server.
JAX-WS endpoint configuration
To create a HTTP/SOAP endpoint that listens for incoming connections to the server, define a
jaxws:element
, as follows:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> ... <jaxws:endpoint id="server" implementor="demo.wssec.server.GreeterImpl" endpointName="s:SoapPort" serviceName="s:SOAPService" address="http://localhost:9001/SoapContext/SoapPort" wsdlLocation="wsdl/hello_world.wsdl" xmlns:s="http://apache.org/hello_world_soap_http"> <jaxws:properties> <entry key="security.signature.username" value="myservicekey"/> <entry key="security.callback-handler" value="demo.wssec.server.ServerCallbackHandler"/> <entry key="security.signature.properties" value="serviceKeystore.properties"/> <entry key="security.encryption.properties" value="serviceKeystore.properties"/> </jaxws:properties> </jaxws:endpoint> ... </beans>
In addition to the usual attributes required for a JAX-WS endpoint, the
jaxws:endpoint
element defines properties for accessing the recipient token, properties for accessing SAML signature-checking tokens, and a reference to a callback handler instance.
Recipient token
The recipient token for the asymmetric binding has both a public key part (used for encrypting outgoing messages) and a private key part (used for signing outgoing messages). These parts of the recipient token are specified by the following properties on the server's
jaxws:endpoint
element:
security.signature.properties
- A WSS4J properties file that defines the properties for accessing the private key part of the recipient token.
security.signature.username
- The alias of the recipient token (X.509 certificate and private key pair) in the Java keystore file.
security.callback-handler
- A callback handler class that returns the password for accessing the private key part of the recipient token.
security.encryption.properties
- A WSS4J properties file that defines the properties for accessing the public key part of the recipient token.
Server-side SAML token interceptor
The SAML token interceptor is automatically installed in the server, whenever the corresponding security policy is configured to use the
IssuedToken
policy. The SAML token interceptor is responsible for verifying the signature of the SAML token received from the client (initiator token).
Hence, it is necessary to configure one or more trusted certificates that can be used to check the signature of the SAML token. The SAML token will be rejected unless it is signed by one of the specified trusted certificates.
As it happens, there is not a dedicated property for specifying these trusted certificates. Instead, the SAML token interceptor re-uses the
security.encryption.properties
property. Any trusted certificates found in the Java keystore file specified by security.encryption.properties
will be used for checking the signature of the SAML token. The configuration of the SAML token interceptor is thus the very same configuration that was used to specify the public key part of the recipient token:
<jaxws:endpoint ... > <jaxws:properties> ... <entry key="security.encryption.properties" value="serviceKeystore.properties"/> </jaxws:properties> </jaxws:endpoint>
In practice, configuring the SAML token interceptor consists of using a Java keystore utility to add the trusted STS X.509 certificate to the Java keystore file that is referenced by
security.encryption.properties
.
Server callback handler
The
jaxws:endpoint
element is also configured with a callback handler (through the security.callback-handler
property), as follows:
// Java package demo.wssec.server; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class ServerCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof WSPasswordCallback) { // CXF WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; if ("myservicekey".equals(pc.getIdentifier())) { pc.setPassword("skpass"); break; } } } } }
In this case, the security callback handler is used solely for the purpose of retrieving the password for accessing the private key part of the recipient token (which has the alias,
myservicekey
).
Related STS configuration
When setting up a server, you must remember to add an appropriate regular expression to the list of known Web service endpoints in the STS. For example, as discussed in the context of configuring the STS, you need to include a regular expression that matches the server's endpoint URL, which is set in the
wssec-sts.xml
file as follows:
<beans ... >
...
<bean id="utService"
class="org.apache.cxf.sts.service.StaticService">
<property name="endpoints" ref="utEndpoints"/>
</bean>
<util:list id="utEndpoints">
<value>http://localhost:(\d)*/SoapContext/SoapPort</value>
</util:list>
...
</beans>
9.2.6. Client Configuration
Overview
Figure 9.8, “Demonstration Client Configuration” shows an overview of the configuration for the demonstration client.
Figure 9.8. Demonstration Client Configuration
Aspects of configuration
The most important aspects of the client configuration are, as follows:
- Configure the connection to the STS (STSClient)—the client uses an
STSClient
instance to connect to the STS. TheSTSClient
instance is a complete client in itself, requiring you to specify the STS Web service address and to specify the relevant security properties for the connection. - Configure the connection to the server—the client must also be configured to connect to the server, including the relevant security properties for the connection and a reference to the
STSClient
instance. - Client callback handler—is used to provide the passwords for private keys and to provide the passwords for UsernameToken credentials.
- Related STS configuration—you must ensure that the client's UsernameToken credentials are made available to the STS, so that the client can be authenticated.
Configure the connection to the STS
You must configure the client so that it is capable of contacting the STS to retrieve an issued SAML token. To enable the STS connection, initialize the client's
security.sts.client
property with an STSClient
instance, as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> ... <jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort" createdFromAPI="true"> <jaxws:properties> ... <entry key="security.sts.client"> <bean class="org.apache.cxf.ws.security.trust.STSClient"> <constructor-arg ref="cxf"/> <property name="wsdlLocation" value="http://localhost:8080/SecurityTokenService/UT?wsdl"/> <property name="serviceName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"/> <property name="endpointName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}UT_Port"/> <property name="properties"> <map> <entry key="security.username" value="alice"/> <entry key="security.callback-handler" value="demo.wssec.client.ClientCallbackHandler"/> <entry key="security.encryption.properties" value="clientKeystore.properties"/> <entry key="security.encryption.username" value="mystskey"/> <entry key="security.sts.token.username" value="myclientkey"/> <entry key="security.sts.token.properties" value="clientKeystore.properties"/> <entry key="security.sts.token.usecert" value="true"/> </map> </property> </bean> </entry> </jaxws:properties> </jaxws:client> ... </beans>
Besides the usual properties required for connecting to a Web service endpoint (specified by the
wsdlLocation
, serviceName
, and endpointName
properties), you must set the following security-related properties:
security.username
- In this demonstration, the STS is configured to authenticate the client using UsernameToken credentials. This property specifies the username part of the UsernameToken credentials.
security.callback-handler
- The callback handler class provides both private key passwords and UsernameToken passwords.
security.encryption.properties
- A WSS4J properties file that defines the properties for accessing the STS X.509 certificate. This certificate is needed by the symmetric binding protocol, which uses it to generate a symmetric session key.
security.encryption.username
- The alias of the X.509 certificate referenced by
security.encryption.properties
. security.sts.token.properties
- A WSS4J properties file that defines the properties for accessing the client's X.509 certificate. This is the certificate that is used to identify the client to the server in the Holder-of-Key scenario. This token gets embedded in the request that is sent to the STS (and is also embedded in the SAML token returned from the STS).
security.sts.token.username
- The alias of the STS X.509 certificate referenced by
security.sts.token.properties
. security.sts.token.usecert
- Setting this boolean property to
true
indicates that the specified token should be included in the request sent to the STS (theRequestSecurityToken
message).
Configure the connection to the server
To configure the connection to the server, set the relevant properties directly on the JAX-WS client bean, as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans ... > ... <jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort" createdFromAPI="true"> <jaxws:properties> <entry key="security.signature.properties" value="clientKeystore.properties"/> <entry key="security.signature.username" value="myclientkey"/> <entry key="security.callback-handler" value="demo.wssec.client.ClientCallbackHandler"/> <entry key="security.encryption.properties" value="clientKeystore.properties"/> <entry key="security.encryption.username" value="myservicekey"/> <entry key="security.sts.client"> <bean class="org.apache.cxf.ws.security.trust.STSClient"> ... </bean> </entry> </jaxws:properties> </jaxws:client> ... </beans>
Because the client-server connection uses an asymmetric binding (with an issued token), the following aspects of security need to be configured.
Configure the client's signing key (also used for decrypting message parts received from the server), using the following properties:
security.signature.properties
- A WSS4J properties file that defines the properties for accessing the client's signing key.
security.signature.username
- The alias of the client's signing key in the corresponding Java keystore file.
security.callback-handler
- The callback handler instance that can return the password for accessing the client's signing key.
Configure the client's encryption key (also used for verifying signatures on message parts received from the server), using the following properties:
security.encryption.properties
- A WSS4J properties file that defines the properties for accessing the client's encryption key (X.509 certificate).
security.encryption.username
- The alias of the client's encryption key in the corresponding Java keystore file.
Configure the client to support the IssuedToken policy by setting the
security.sts.client
property, as already described in the section called “Configure the connection to the STS”.
Client callback handler
The client callback handler class is multi-purpose. It is capable of returning both passwords for private keys and the password part of UsernameToken credentials. In this demonstration, the client callback handler class is defined as follows:
// Java package demo.wssec.client; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class ClientCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof WSPasswordCallback) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; if ("myclientkey".equals(pc.getIdentifier())) { pc.setPassword("ckpass"); break; } else if ("alice".equals(pc.getIdentifier())) { pc.setPassword("clarinet"); break; } else if ("bob".equals(pc.getIdentifier())) { pc.setPassword("trombone"); break; } else if ("eve".equals(pc.getIdentifier())) { pc.setPassword("evekpass"); break; } } } } }
Related STS configuration
In this demonstration, the STS authenticates the client by checking the client's UsernameToken credentials. Hence, you must ensure that the client's UsernameToken credentials are known to the STS. In this demonstration, the known UsernameToken credentials are embedded in the code of the STS callback handler class, the section called “STS callback handler ”.
9.2.7. Build and Run the Demonstration
Steps to run the demonstration
To build and run the STS demonstration, perform the following steps:
- Open a command prompt and change directory to the
CXFInstallDir/samples/sts
directory. Enter the following command to build the demonstration:mvn clean install
- To start the STS process, enter the following command:
mvn -Psts
- To start the WS server process, open a new command prompt, change directory to the
CXFInstallDir/samples/sts
directory, and enter the following command:mvn -Pserver
- To run the WS client, open a new command prompt, change directory to the
CXFInstallDir/samples/sts
directory, and enter the following command:mvn -Pclient
Because CXF logging has been enabled, you should see the SOAP messages being logged to each of the command windows. If the client runs successfully, you should see the following message in the client command window:... -------------------------------------- Server responded with: Hello YourName