Monday, November 30, 2015

Javascript Object Signing and Encryption (JOSE) support in Apache CXF - part I

The Javascript Object Signing and Encryption (JOSE) specifications cover how to sign and encrypt data using JSON. Apache CXF has excellent support for all of the JOSE specifications (see the documentation here), thanks largely to the work done by my colleague Sergey Beryozkin. This is the first in a series of blog posts describing how to use and implement JOSE for your web services using Apache CXF. In this post, we will cover how to sign content using the JSON Web Signature (JWS) specification.

1) Test Cases:

Let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
For now let's look at the JWSSignatureTest. These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code uses the CXF WebClient API to sign the message payload by adding a specific provider. The message in turn is validated by a provider on the receiving side. You can run the test via the command line "mvn test -Dtest=JWSSignatureTest", and the message requests and responses will appear in the console.

For example, here is the output of the "testSignatureCompact" request. The Payload consists of the concatenated (+ separated by a '.') BASE-64 URL encoded JWS header (e.g. containing the signature algorithm, amongst other values), the BASE-64 URL encoded message payload, and the BASE-64 URL encoded signature value.


2) Compact vs. JSON Serialization

The JWS specification defines two different ways of serializing the signatures. Compact serialization is a URL-safe representation that is convenient to use when you only have a single signing entity. JSON serialization resprents the JWS structures as JSON objects, and allows multiple signatures to be included in the request as a result. The JWSSignatureTest includes both examples ("testSignatureListProperties" and "testSignatureCompact"). It's very easy to experiment with both approaches, as you only have to use different providers on both the client + receiving sides:
  • JSON Serialization: JwsJsonWriterInterceptor (out) + JwsJsonContainerRequestFilter (in)
  • Compact: JwsWriterInterceptor (out) + JwsContainerRequestFilter (in)
3) Security Configuration

As well as adding the desired providers, it is also necessary to specify the security configuration to set the appropriate algorithms, keys, etc. to use. The CXF wiki has an extensive list of all of the different security configuration properties. For signature, we need to first load the signing key (either a JKS keystore or else a JSON Web Key (JWK) is supported).

As well as defining a signing key, we also need to configure the signing algorithm. The list of acceptable signing algorithms for JWS is defined by the JSON Web Algorithms (JWA) spec. For signature, this boils down to a public key signature scheme based on either RSA or EC-DSA, or a symmetric scheme using HMAC.

For example, the tests use the following configuration to load a private key from a Java KeyStore, and to use the signature scheme of RSASSA-PKCS1-v1_5 using SHA-256:
The service side configuration is largely the same, apart from the fact that we don't need to specify the "rs.security.key.password" configuration tag, as we don't need to load the private key. The signature algorithm must be specified to impose a constraint on the acceptable signature algorithm.

4) Signing XML payload

The JWS payload (the content to be signed) can be any binary content and not just a JSON Object. This means that we can use JWS to sign an XML message. This is a really cool feature of the specification in my opinion, as it essentially removes the need to use XML Signature to sign XML payload. An example of this is included in the JWSSignatureTest. The configuration is exactly the same as for the JSON case.

5) Including the signing key

It is possible to include the signing certificate/key in the JWS header by setting one of the following properties:
  • rs.security.signature.include.public.key -  Include the JWK public key for signature in the "jwk" header.
  • rs.security.signature.include.cert - Include the X.509 certificate for signature in the "x5c" header.
  • rs.security.signature.include.key.id - Include the JWK key id for signature in the "kid" header.
  • rs.security.signature.include.cert.sha1- Include the X.509 certificate SHA-1 digest for signature in the "x5t" header.
One advantage of including the entire certificate is that the service doesn't need to store the client certificate locally, but only the issuing certificate.

Monday, November 16, 2015

New security advisory for Apache CXF

A new security advisory has been released for Apache CXF, which is fixed in the 3.1.3, 3.0.7 and 2.7.18 releases.
  • CVE-2015-5253: Apache CXF SAML SSO processing is vulnerable to a wrapping attack
Apache CXF supports the SAML SSO protocol with JAX-RS web service endpoints. It is possible for a malicious user to construct a SAML Response (the response from the SAML SSO IdP to the endpoint) via a so-called "wrapping attack", to allow that user to log in instead of the authenticated user associated with the signed SAML Assertion.

Please see the Apache CXF security advisories page for more information.

Wednesday, November 11, 2015

Testing Kerberos with Web Services using Apache Kerby

The previous blog post described how to use Apache Directory to easily create a KDC via Java annotations for kerberos integration testing. In this post, we will look at an alternative way of setting up a KDC for integration testing using Apache Kerby.

Apache Kerby is a new subproject of Apache Directory that aims to provide a complete Kerberos solution in Java. Version 1.0.0-RC1 has recently been released and is available for testing. Apache Kerby consists of both a KDC as well as a client API, that is completely independent of the GSS API that comes with Java. A key selling point of Apache Kerby is that it is very easy and fast to setup and deploy a KDC. It is possible to set up a KDC completely in code, without having to edit any configuration files or configure any system properties.

Let's see how this is done by looking at a project I created on github:
  • cxf-kerberos-kerby: This project contains a number of tests that show how to use Kerberos with Apache CXF, where the KDC used in the tests is based on Apache Kerby.
The KDC is launched in the test-code, and is pretty much as straightfoward as the following code snippet:

The first block of code configures the host, realm, transports and ports, while the second creates the client, service and TGT principals that are used in the tests. No configuration files required! As well as showing how to use Apache CXF to authenticate using both Kerberos and Spnego for a JAX-WS service, the AuthenticationTest also includes unit tests for getting a service ticket from the Kerby KDC using the Java GSS API as well as the Kerby client API. Using the Kerby client API is as simple as this:


Have fun playing around with Apache Kerby and please join and contribute to the project if you are interested!