Tuesday, October 21, 2014

Kerberos Credential Delegation support in Apache CXF

Apache CXF provides full support for integrating Kerberos with JAX-WS and JAX-RS services. A previous tutorial (here and here) described how to set up Kerberos with WS-Security in CXF, where the client obtains a Kerberos service ticket and encodes it in the security header of the request, and where it is validated in turn by the service. In this post we will discuss support for kerberos credential delegation for JAX-WS clients and services in Apache CXF. For more information on using kerberos with JAX-RS please consult the CXF documentation.

1) Kerberos Client Configuration

CXF provides a number of JAX-WS properties that can be used to configure Kerberos on the client side (documented here under "Kerberos Configuration Tags"). Essentially there are two different ways of doing it. The client must explicitly allow kerberos credential delegation by setting a property.

1.1) Create and configure a KerberosClient Object directly

The KerberosClient in the CXF WS-Security runtime module is used to retrieve a kerberos ticket. It can be configured by setting various properties and then referenced via the JAX-WS property:
  • ws-security.kerberos.client - A reference to the KerberosClient class used to obtain a service ticket.
The "requestCredentialDelegation" property of the KerberosClient must be set to "true" to allow credential delegation. Here is an example in Spring:

<bean class="org.apache.cxf.ws.security.kerberos.KerberosClient" id="kerberosClient">
        <constructor-arg ref="cxf"/>
        <property name="contextName" value="bob"/>
        <property name="serviceName" value="bob@service.ws.apache.org"/>
        <property name="requestCredentialDelegation" value="true"/>
</bean>

<jaxws:client name="{service}port" createdFromAPI="true">
        <jaxws:properties>
            <entry key="ws-security.kerberos.client" value-ref="kerberosClient"/>
        </jaxws:properties>
</jaxws:client>

1.2) Use JAX-WS properties to configure Kerberos

Rather than use the KerberosClient above, it is possible to configure Kerberos via JAX-WS properties:
  • ws-security.kerberos.jaas.context - The JAAS Context name to use for Kerberos.
  • ws-security.kerberos.spn - The Kerberos Service Provider Name (spn) to use.
  • ws-security.kerberos.is.username.in.servicename.form - Whether the Kerberos username is in servicename form or not.
  • ws-security.kerberos.use.credential.delegation - Whether to use credential delegation or not in the KerberosClient.
  • ws-security.kerberos.request.credential.delegation - Whether to request credential delegation or not in the KerberosClient.
The latter property must be set to "true" on the client side to allow kerberos credential delegation.

2) Kerberos Service Configuration

A JAX-WS service validates a kerberos ticket received in the security header of a request via a KerberosTokenValidator. Here is an example:

<bean id="kerberosValidator"
           class="org.apache.wss4j.dom.validate.KerberosTokenValidator">
        <property name="contextName" value="bob"/>
        <property name="serviceName" value="bob@service.ws.apache.org"/>
</bean>
<jaxws:endpoint ...>
        <jaxws:properties>
            <entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
        </jaxws:properties>
</jaxws:endpoint>
   
3) Using Kerberos Credential Delegation

After a service has validated a kerberos token sent by the client, it can obtain another kerberos token "on behalf of" the client, assuming the client enabled credential delegation in the first place. To use the client credential for delegation the "useDelegatedCredential" property of the KerberosClient must be set to "true" (see here), or else the JAX-WS property "ws-security.kerberos.use.credential.delegation" must be set to "true" if not configuring Kerberos via the KerberosClient Object.

To see how a concrete use-case for this functionality, take a look at the KerberosDelegationTokenTest in the CXF STS advanced systests. Here we have a backend service which requires a SAML Token issued by an STS. However, the clients only know how to obtain a Kerberos token. So we have an intermediary service which requires a Kerberos token. The clients enable credential delegation + send a ticket to the Intermediary. The Intermediary validates the ticket, then uses it to obtain a Kerberos token "OnBehalfOf" the client, which in turn is used to authenticate to the STS + retrieve a SAML Token, which is then forwarded on to the backend service.

2 comments:

  1. I have a cxf webservice client deploy on JBoss 7.1 . The client need to do kerberos authentication with the remote web service (use a keytab file).My application and the remote web service share the same Active directory (diffrents host in the same company).
    What changes I have to do in the Jboss configuration in order to support this authentication ?

    ReplyDelete

  2. Wow! Great post! The content is very rich, and I really like it.

    Server 2016
    Microsoft Server 2016 Support

    ReplyDelete