Tuesday, June 28, 2011

Custom token validation in Apache CXF 2.4

A previous blog post has covered validators in Apache WSS4J 1.6, why they were introduced, what default implementations ship with WSS4J, etc. It ends with a paragraph on how to use a custom Validator implementation with Apache CXF 2.4. This post expands further on this topic.

1) Use-cases for custom Token Validation

Let's consider first of all the use-cases for specifying a custom Validator implementation in CXF. When a security header is being processed by WSS4J, it delegates each security token to a Processor implementation, depending on the QName of the token. In WSS4J 1.6, Processors do not do any validation of extracted credentials from a token, they merely process it, make sure it meets basic requirements, etc. Validation is delegated to a Validator interface which is associated with that Processor implementation.

However, there are many possible use-cases where a user may wish to replace or remove or extend the default validation behaviour associated with a particular security token. Some examples include:
  1. Validating a UsernameToken, where the CallbackHandler implementation does not have access to the password.
  2. Validating a BinarySecurityToken of some custom type.
  3. Validating the attributes of a received SAML Assertion
  4. Validating a Timestamp in a more tolerant manner than the default.
  5. Dispatching a received security token to a third-party security service for validation/authentication.
2) Configuring custom Validators in CXF
    The CXF SecurityConstants class (javadoc) defines some configuration items to override the default validators used to validate a received security token. The values associated with each configuration option must correspond to an implementation of the Validator interface. The configuration tags are:
    1. "ws-security.ut.validator" - Override UsernameToken validation.
    2. "ws-security.saml1.validator" - Override SAML1 token validation.
    3. "ws-security.saml2.validator" - Override SAML2 token validation.
    4. "ws-security.timestamp.validator" - Override Timestamp validation.
    5. "ws-security.signature.validator" - Override trust verification on a signature
    6. "ws-security.bst.validator" - Override BinarySecurityToken validation.
    To disable the validation of a particular token, specify the NoOpValidator as the value of the configuration tag corresponding to that token.

    3) Using Validators with WS-Trust

    To see the power and flexibility of the approach of separating processing from validation, consider the STSTokenValidator that ships with CXF 2.4. This validator implementation has the ability to dispatch a received BinarySecurityToken, UsernameToken, or SAML Assertion to an STS (Security Token Service) for validation via WS-Trust. On invocation, it delegates the credential to another validator (STSSamlAssertionValidator). This validator essentially catches an exception caused by a signature validation failure of the SAML Assertion and sets a flag. Only if signature validation is unsuccessful does the STSTokenValidator dispatch the token to the STS for validation.

    An example of how to configure the STSTokenValidator to validate a SAML1 Assertion against an STS in spring is as follows:

    <jaxws:endpoint ...>
        <entry key="ws-security.saml1.validator">
          <bean class="org.apache.cxf.ws.security.trust.STSTokenValidator"/>
        <entry key="ws-security.sts.client">
          <bean class="org.apache.cxf.ws.security.trust.STSClient">
            <constructor-arg ref="cxf"/>
            <property name="wsdlLocation" value="..."/>
            <property name="serviceName" value=".../>
            <property name="endpointName" value="..."/>

    The STSTokenValidator also has the ability to obtain a transformed token from the STS and store it in the credential, where it is available as part of the WSSecurityEngineResult under the TAG_TRANSFORMED_TOKEN tag.


    1. Could you post the source code for an example?

    2. There are links to source in the blog post. If you want to see a system test that uses a custom Validator, take a look at the SamlTokenTest in CXF (the Server directory has a custom SAML Validator):



    3. Thanks Colm. Useful, clear and interesting info.

    4. Would I write my own ws-security.bst.validator for validating X509 certificates via XKMS?

    5. Hi Jan,

      Yes I think so. However, you might need to set it as the signature validator as well, if the X509 certificate is used to verify a signature.


    6. Interesting!

      What would be the way to configure overrides in Axis2 Rampart 1.6.2? Trying to implement directory lookup on UsernameToken with given password the new way with validators, but can't find any documentation on this topic at Rampart website.


    7. Best to ask on the Rampart dev list - I don't know whether they expose configuration for this or not.


      1. I actually went over there and looked through activity and roadmaps. They have an issue registered for it but at low priority and not included in the roadmaps for next minor or next major release.

        Thanks for your reply, Colm.

    8. hello, i need to just validate signatures on saml tokens. questions, if a signature failed, what use is the call to the STS (behavior you described above in cfx 2.4)? does this work the same way, independent of saml profile (e.g. bearer)? and without spring, is this set up in the ws-securitypolicy section of the wsdl (for a soap service)?

    9. The use-case for falling back to the STS is when the service is not configured with the signature validation key required to validate the SAML Token. No it's not set up in a security policy, as it's a configuration detail of the service. You have to configure it either via spring or in code.