Friday, March 29, 2019

HTTP Signature support in Apache CXF

Apache CXF provides support for the HTTP Signatures draft spec since the 3.3.0 release. Up to this point, JAX-RS message payloads could be signed using either XML Security or else using JOSE. In particular, the JOSE functionality can be used to also sign HTTP headers. However it doesn't allow the possibility to sign the HTTP method and Path, something that HTTP Signature supports. In this post we'll look at how to use HTTP Signatures with Apache CXF.

I uploaded a sample project to github to see how HTTP Signature can be used with CXF:
  • cxf-jaxrs-httpsig: This project contains a test that shows how to use the HTTP Signature functionality in Apache CXF to sign a message to/from a JAX-RS service.

1) Client configuration

The client configuration to both sign the outbound request and verify the service response is configured in the test code:

Two JAX-RS providers are added - CreateSignatureInterceptor creates a signature on the outbound request, and VerifySignatureClientFilter verifies a signature on the response. The keys used to sign the request and verify the response are configured in properties files, that are referenced via the "rs.security.signature.out.properties" and "rs.security.signature.in.properties" configuration tags:

Here we can see that a keystore is being used to retrieve the private key for signing the outbound request. If you wish to retrieve keys from some other source, then instead of using configuration properties it's best to configure the MessageSigner class directly on the CreateSignatureInterceptor.

By default CXF will add all HTTP headers to the signature. In addition, a client will also include the HTTP method and path using the "(request-target)" header. Also if the payload is not empty, it will be digested with the digest added to a "Digest" HTTP header, which is also signed. This provides payload integrity. By default, the signature algorithm is "rsa-sha256", of course it is possible to configure this. A secured request using HTTP signature looks like the following:


2) Service configuration

The service configuration is defined in spring. Two different JAX-RS providers are used on the service side - VerifySignatureFilter is used to verify a signature on the client request, and CreateSignatureInterceptor is used to sign the response message as per the client request.

For more information on how to use HTTP Signatures with Apache CXF, refer to the CXF documentation.

Thursday, March 21, 2019

Using authorization with JWT tokens in Apache CXF

JSON Web Tokens (JWT) have been covered extensively on this blog (for example here). In this post we will cover how JWT tokens can be used for authorization when sent to a JAX-RS web service in Apache CXF. In particular, we will show how Apache CXF 3.3.0 supports claims based access control with JWT tokens.

1) JWT with RBAC

JWT tokens can be used for the purpose of authentication in a web service context, by verifying the signature on the token and taking the "sub" claim as the authenticated principal. This assumes no proof of possession of the token, something we will revisit in a future blog post. Once this is done we have the option of performing an authorization check on the authenticated principal. This can be done easily via RBAC by using a claim in the token to represent a role.

Apache CXF has a SimpleAuthorizingInterceptor class, which can map web service operations to role names. If the authenticated principal is not associated with the role that is required to access the operation, then an exception is thrown. Here is an example of how to configure a JAX-RS web service in CXF with the SimpleAuthorizingInterceptor for JWT:
Here the JwtAuthenticationFilter has been configured with a "roleClaim" property of "role". It then extracts the configured claim from the authenticated token and uses it for the RBAC authorization decision. To see this functionality in action, look at the corresponding test-case in my github repo.

2) JWT with CBAC

Since CXF 3.3.0, we can also use the Claims annotations in CXF (that previously only worked with SAML tokens) to perform authorization checks on requests that contain JWT tokens. This allows us to specify more fine-grained authorization requirements on the token, as opposed to the RBAC approach above. For example, we can annotate our service endpoint as follows:

Here we can see a "role" claim is required which must match either the value "boss" or "ceo". We can enable claims based authorization by adding the ClaimsAuthorizingFilter as a provider of the endpoint, with the "securedObject" parameter being the service implementation:

We can specify multiple claims annotations and combine them in different ways, please see the CXF webpage for more information. To see this functionality in action, look at the corresponding test-case in my github repo.