Wednesday, February 22, 2012

WS-Trust SPNego support in Apache CXF

Support for SPNego using WS-Trust has been added to Apache CXF and will be available in the forthcoming 2.4.7 and 2.5.3 releases. This new functionality allows a CXF client to integrate with WCF 4.0, as WCF 4.0 uses message level NTLM/Kerberos based on SPNego using WS-Trust. See the following blog for an in-depth explanation of how to do exactly this. Support for obtaining and validating SPNEGO tokens was added to Apache WSS4J in the 1.6.4 release. WSS4J 1.6.5 will feature support for making the Spnego Client and Service Action classes pluggable, so that the user can specify a custom means of obtaining the ticket.

Using WS-Trust for SPNego is described in the following application note. The client contacts a KDC and obtains a SP Negotiation token, which it sends to the service provider via WS-Trust. If the negotiation is incomplete, the service provider can respond to the client to continue the negotiation. Once the negotiation is complete, a WS-Trust RequestedProofToken is created which contains a secret key that has been encrypted with the negotiated key, and this is returned to the client along with an Authenticator and a SecurityContextToken. The client can decrypt the EncryptedKey, and use this key with a symmetric encryption or signature algorithm to secure a request.

Note that the focus is on making sure that a CXF client can interoperate with WCF, and hence the STS support for SPNego is only intended as a means of testing the client code. In particular, the STS does not return an Authenticator, which is required by the spec. One additional limitation is that the STS client does not currently support continued negotation.

1) Running the WS-Trust SPNego system tests in Apache CXF 

To run the WS-Trust SPNego system tests in CXF, it is first necessary to set up a KDC correctly. Follow the instructions given in section 1 in a previous blog post which describes how to run the Kerberos system tests in CXF. Next, make sure that the JDK has unlimited security policies installed, and then checkout the CXF trunk via:
svn co
Go into the "trunk" directory, and compile and install CXF via "mvn -Pfastinstall" (this will avoid running tests). Finally go into the WS-Security system tests in "systests/ws-security". The SpnegoTokenTest contains two tests, which are @Ignore'd by default. Open and comment out the "@org.junit.Ignore" entries for both tests. If you want to see the message exchanges, open src/test/resources/, and change the level from WARNING to INFO, and the ConsoleHandler level from SEVERE to INFO. Finally, run the tests via:

        mvn test -Dtest=SpnegoTokenTest

1.1) WS-SecurityPolicy configuration

The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the tests:
  • DoubleItSpnegoSymmetricProtectionPolicy: This uses a Symmetric binding, where the protection token is a SpnegoContextToken.
  • DoubleItSpnegoSymmetricProtectionDerivedPolicy: This uses a Symmetric binding, where the protection token is key derived from a SpnegoContextToken.
1.2) Kerberos LoginModule configuration

Both the CXF client and service endpoint use JAAS to authenticate to the KDC. The JAAS file used as part of the system test is passed to the tests via the System property "". The client (alice) uses the following login module:
alice { required
    refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"
and the service endpoint (bob) uses:
bob { required
    refreshKrb5Config=true useKeyTab=true storeKey=true
    keyTab="/etc/bob.keytab" principal="bob/";
1.3) Client and Service endpoint configuration

Both the service and client endpoints are spring-loaded. The contain the following JAX-WS properties, which are defined in SecurityConstants:
  •  "ws-security.kerberos.jaas.context" - This refers to the JAAS context given in the configuration file above. The clients use a value of "alice", and the service endpoints use "bob".
  • "ws-security.kerberos.spn"- This is only configured on the client side, and specifies the Kerberos Service Provider Name ("").
Finally, there is one additional JAX-WS property that can be defined on the client, if you want to plug in a custom WSS4J SpnegoClientAction implementation:
  • "ws-security.spnego.client.action" - The SpnegoClientAction implementation to use for SPNEGO. This allows the user to plug in a different implementation to obtain a service ticket. See here for more details on how to use this property.