Monday, February 15, 2016

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

This is the fourth and final article in a series of posts on support for Javascript Object Signing and Encryption (JOSE) in Apache CXF. The first article covered how to sign content using JWS, while the second article showed how to encrypt content using JWE. The third article described how to construct JWT Tokens, how to sign and encrypt them, and how they can be used for authentication and authorization in Apache CXF. In this post, we will show how the CXF Security Token Service (STS) can be leveraged to issue and validate JWT Tokens.

1) The CXF STS

Apache CXF ships with a powerful and widely deployed STS implementation that has been covered extensively on this blog before. Clients interact with the STS via the SOAP WS-Trust interface, typically asking the STS to issue a (SAML) token by passing some parameters. The STS offers the following functionality with respect to tokens:
  • It can issue SAML (1.1 + 2.0) and SecurityContextTokens.
  • It can validate SAML, UsernameToken and BinarySecurityTokens.
  • It can renew SAML Tokens
  • It can cancel SecurityContextTokens.
  • It can transform tokens from one type to another, and from one realm to another.
Wouldn't it be cool if you could ask the STS to issue and validate JWT tokens as well? Well that's exactly what you can do from the new CXF 3.1.5 release! If you already have an STS instance deployed to issue SAML tokens, then you can also issue JWT tokens to different clients with some simple configuration changes to your existing deployment.

2) Issuing JWT Tokens from the STS

Let's look at the most common use-case first, that of issuing JWT tokens from the STS. The client specifies a TokenType String in the request to indicate the type of the desired token. There is no standard WS-Trust Token Type for JWT tokens as there is for SAML Tokens. The default implementation that ships with the STS uses the token type "urn:ietf:params:oauth:token-type:jwt" (see here).

The STS maintains a list of TokenProvider implementations, which it queries in turn to see whether it is capable of issuing a token of the given type. A new implementation is available to issue JWT Tokens - the JWTTokenProvider. By default tokens are signed via JWS using the STS master keystore (this is controlled via a "signToken" property of the JWTTokenProvider). The keystore configuration is exactly the same as for the SAML case. Tokens can also be encrypted via JWE if desired. Realms are also supported in the same way as for SAML Tokens.

The claims inserted into the issued token are obtained via a JWTClaimsProvider Object configured in the JWTTokenProvider. The default implementation adds the following claims:
  • The current principal is added as the Subject claim.
  • The issuer name of the STS is added as the Issuer claim.
  • Any claims that were requested by the client via the WS-Trust "Claims" parameter (that can be handled by the ClaimManager of the STS).
  • The various "time" constraints, such as Expiry, NotBefore, IssuedAt, etc.
  • Finally, it adds in the audience claim obtained from an AppliesTo address and the wst:Participants, if either were specified by the client.
The token that is generated by the JWTTokenProvider is in the form of a String. However, as the token will be included in the WS-Trust Response, the String must be "wrapped" somehow to form a valid XML Element. A TokenWrapper interface is defined to do precisely this. The default implementation simply inserts the JWT Token into the WS-Trust Response as the text content of a "TokenWrapper" Element.
3) Validating JWT Tokens in the STS

As well as issuing JWT Tokens, the STS can also validate them via the WS-Trust Validate operation. A new TokenValidator implementation is available to validate JWT tokens called the JWTTokenValidator. The signature of the token is first validated by the STS truststore. Then the time related claims of the token are checked, e.g. is the token expired or is the current time before the NotBefore time of the token, etc.

A useful feature of the WS-Trust validate operation is the ability to transform tokens from one type to another. Normally, a client just wants to know if a token is valid or not, and hence receives a "yes/no" response from the STS. However, if the client specifies a TokenType that doesn't corresponds to the standard "Status" TokenType, but instead corresponds to a different token, the STS will validate the received token and then generate a new token of the desired type using the principal associated with the validated token.

This "token transformation" functionality is also supported with the new JWT implementation. It is possible to transform a SAML Token into a JWT Token, and vice versa, something that could be quite useful in a deployment where you need to support both REST and SOAP services for example. Using a JWT Token as a WS-Trust OnBehalfOf/ActAs token is also supported.

7 comments:

  1. Hi Colm,

    Can you please provide me an example token transformation from JWT token to SAML token. Thanks in advance

    ReplyDelete
  2. There's a test you can run here: https://github.com/apache/cxf/blob/29e5bb404e6b44a643e9228712f495244ea275e2/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/STSRESTTest.java#L1093

    ReplyDelete
  3. Thanks Colm like org.apache.cxf.sts.token.delegation.SAMLDelegationHandler
    dont we have JWTDelegationHandler to verify TokenDelegation? Thanks in advance

    ReplyDelete
  4. There isn't one available by default, but you could write your own and plug it in to the STS.

    ReplyDelete
  5. Hi Colm,
    Thanks allot for reply, Yes I am writing JWTDelegationHandler class as a security expert can u guide me what all namespaces to validate in TokenWrapper in canHandleToken method which all namespaces I should cover ? like SAML we have SAML_NS and SAML2_NS in assertion

    ReplyDelete
  6. I guess you won't need namespaces here but instead need to get the received token and see if it's a JWT or not

    ReplyDelete
  7. Very Good morning Colm, thanks allot for inputs Yes I am validating JWT token it looks good.

    ReplyDelete