This section describes how to customize the server configuration, so that it is capable of checking and confirming the signature that appears in the SAML tokens received from the client.
The underlying implementation of WS-Security and WS-Trust is provided by a set of WSS4J interceptors, based on the open source Apache WSS4J security toolkit. These interceptors are automatically installed into a server endpoint, if the endpoint is associated with a WS-SecurityPolicy policy in the server's WSDL file. In the absence of WSDL policies, it is also possible to install the WSS4J interceptors explicitly—see the WS-Security page.
In this example, the SAML token issued by the STS is signed by the STS certificate.
The issued SAML token also declares the subject confirmation method to be
bearer
, which implies that the server should trust the bearer of the SAML
token, only if the token's signature is confirmed.
Hence, the server must be configured so that it can confirm incoming signatures. The
details of this type of configuration are given in Providing Encryption Keys and Signing
Keys and, essentially, it consists of setting the
ws-security.encryption.properties
property in the relevant
jaxws:endpoint
element. Confusingly, although this property is named
encryption, it is also used for confirming signatures. The
ws-security.encryption.properties
property accesses the STS certificate,
which is used to confirm the token's signature.
Because the current example is intended mainly to illustrate how to integrate a client with WS-Trust, the server side has not been fully implemented. Although the server (as configured here) is capable of understanding and processing security headers from the client, the server is not properly configured to enforce any authentication or authorization policies. In particular, if a client fails to send an authentication token, the server will happily process the request in any case.
A properly implemented server would be augmented by policies that require a particular kind of authentication token and the server would check the value of the received token, as appropriate.
Perform the following steps to configure the server-side interceptor:
Comment out the Java code for instantiating the Web service endpoint (in this example, it is more convenient to instantiate the endpoint in XML, because it enables you to specify all of the endpoint's properties in one place).
Edit the
Server.java
file from thewsdl_first_https/src/demo/hw_https/server
directory. Look for the lines of Java code that instantiate the Web service endpoint (highlighted below) and enclose them between/*
and*/
, so that the lines are commented out as shown.package demo.hw_https.server; ... public class Server { protected Server() throws Exception { System.out.println("Starting Server"); SpringBusFactory bf = new SpringBusFactory(); URL busFile = Server.class.getResource("CherryServer.xml"); Bus bus = bf.createBus(busFile.toString()); bf.setDefaultBus(bus); /* Object implementor = new GreeterImpl(); String address = "https://localhost:9001/SoapContext/SoapPort"; Endpoint.publish(address, implementor); */ } ...
Create the Web service endpoint in XML. Edit the
CherryServer.xml
file from thewsdl_first_https/src/demo/hw_https/server
directory. Add the followingjaxws:endpoint
element as a child of thebeans
element to instantiate the Web service endpoint.<beans ...> ... <jaxws:endpoint id="server" endpointName="s:SoapPort" serviceName="s:SOAPService" implementor="demo.hw_https.server.GreeterImpl" address="https://localhost:9001/SoapContext/SoapPort" wsdlLocation="wsdl/hello_world_server.wsdl" xmlns:s="http://apache.org/hello_world_soap_http" > <jaxws:properties> <entry key="ws-security.encryption.properties" value="sts/sts.properties" /> </jaxws:properties> </jaxws:endpoint> ... </beans>
Notice how the
wsdlLocation
attribute points at thehello_world_server.wsdl
file, which is the copy of the WSDL contract that excludes the IssuedToken policy. Thews-security.encryption.properties
property points at the file,sts/sts.properties
, which will be defined in a later step.Enable policy support and logging as follows. Continue editing the
CherryServer.xml
file. Add the followingcxf:bus
element as a child of thebeans
element:<beans ...> ... <cxf:bus xmlns:cxf="http://cxf.apache.org/core"> <cxf:features> <p:policies xmlns:p="http://cxf.apache.org/policy"/> <cxf:logging/> </cxf:features> </cxf:bus> ... </beans>
Add the requisite XML schema locations. Continue editing the
CherryServer.xml
file. To support thejaxws
andcxf
namespace prefixes, add the highlighted schema locations and define thejaxws
namespace prefix, as follows:<beans xmlns="http://www.springframework.org/schema/beans" 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/configuration/security http://cxf.apache.org/schemas/configuration/security.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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 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.xsd"> ...
Now define the
sts.properties
file, which specifies the WSS4J properties for accessing the STS certificate. In thewsdl_first_https/sts
directory, use your favorite text editor to create the file,sts.properties
, containing the following property settings:org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=JKS org.apache.ws.security.crypto.merlin.keystore.file=sts/certs/stsstore.jks org.apache.ws.security.crypto.merlin.keystore.password=stsspass org.apache.ws.security.crypto.merlin.keystore.alias=mystskey
For more details on these WSS4J properties, see Providing Encryption Keys and Signing Keys.
Add Maven instructions to copy the
sts.properties
file into thetarget/classes/sts
directory (so that thests.properties
file gets included in the WAR package). Edit thepom.xml
file from thewsdl_first_https/
directory and search for thecopyxmlfiles
target of the Mavenantrun
plug-in. Under configuration tasks, add the highlighted lines as shown in the following fragment:<project ...> ... <build> ... <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>copyxmlfiles</id> ... <configuration> <tasks> <copy file="${basedir}/src/demo/hw_https/server/CherryServer.xml" todir="${basedir}/target/classes/demo/hw_https/server" /> <copy file="${basedir}/src/demo/hw_https/client/WibbleClient.xml" todir="${basedir}/target/classes/demo/hw_https/client" /> <copy file="${basedir}/src/demo/hw_https/client/InsecureClient.xml" todir="${basedir}/target/classes/demo/hw_https/client" /> <copy todir="${basedir}/target/classes/certs"> <fileset dir="${basedir}/certs" /> </copy> <copy todir="${basedir}/target/classes/sts"> <fileset dir="${basedir}/sts" /> </copy> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> ... </project>
Note This step is only necessary, because this
wsdl_first_https
Maven project is set up in a slightly unconventional way. Normally, in a Maven project, you put all of your resource files undersrc/main/resources/
, which Maven automatically copies into the target package.