Friday, October 24, 2014

Two new security advisories for Apache CXF

Two new security advisories have been released for Apache CXF, please see the CXF security advisories page for the details:
  • CVE-2014-3623: Apache CXF does not properly enforce the security semantics of SAML SubjectConfirmation methods when used with the TransportBinding
  • CVE-2014-3584: Apache CXF JAX-RS SAML handling is vulnerable to a Denial of Service (DoS) attack
If you are using SAML SSO or else SAML tokens with the WS-SecurityPolicy Transport binding you should upgrade to either CXF 2.7.13 or 3.0.2.

Thursday, October 23, 2014

Apache CXF Authentication and Authorization test-cases IV

This is the fourth in a series of posts on authentication and authorization test-cases for web services using Apache CXF. The first focused on different ways to authenticate and authorize UsernameTokens for JAX-WS services. The second looked at more advanced examples such as using Kerberos, WS-Trust, XACML, etc. The third looked at different ways of achieving SSO in CXF for both JAX-WS and JAX-RS services. This post gives some examples of authenticating and authorizing JAX-RS services in Apache CXF. I also included the SSO examples relevant to JAX-RS from the previous post. The projects are:
  • cxf-jaxrs-xmlsecurity: This project shows how to use XML Signature (and Encryption) to secure JAX-RS services. In particular, see the AuthenticationTest.
  • cxf-jaxrs-sts: This project demonstrates how to use HTTP/BA for authentication for JAX-RS, where the credentials are dispatched as a UsernameToken are dispatched to an STS instance for authentication. In addition, the project shows how to authorize the request by asking the STS for a SAML Token containing the roles of the user.
  • cxf-kerberos: This project (covered previously for JAX-WS) has been updated with a test that shows how to use Kerberos with JAX-RS.
  • cxf-saml-sso: This project shows how to leverage SAML SSO with Apache CXF to achieve SSO for a JAX-RS service. CXF supports the POST + redirect bindings of SAML SSO for JAX-RS endpoints. As part of this demo, a mock CXF-based IdP is provided which authenticates a client using HTTP/BA and issues a SAML token using the CXF STS. Authorization is also demonstrated using roles embedded in the issued SAML token. 
  • cxf-fediz-federation-sso: This project shows how to use the new CXF plugin of Apache Fediz 1.2.0 to authenticate and authorize clients of a JAX-RS service using WS-Federation. This feature will be documented more extensively at a future date, and is considered experimental for now. Please play around with it and provide feedback to the CXF users list.

Wednesday, October 22, 2014

Apache CXF Fediz 1.1.2 released

Apache CXF Fediz 1.1.2 has been released. Apache CXF Fediz is a Single Sign-On (SSO) solution based on the WS-Federation Passive Requestor Profile. It consists of an Identity Provider (IdP) which leverages the Apache CXF STS to issue tokens, as well as a number of container-specific plugins (Jetty, Tomcat, Spring, etc.) to enable SSO for web applications. The issues fixed in the new release include an upgrade to CXF 2.7.13, support for claims mapping in the STS, kerberos authentication support in the IdP, amongst other fixes.

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.

Tuesday, October 14, 2014

Using JAAS with Apache CXF

Apache CXF supports a wide range of tokens for authentication (SAML, UsernameTokens, Kerberos, etc.), and also offers different ways of authenticating these tokens. A standard way of authenticating a received token is to use a JAAS LoginModule. This article will cover some of the different ways you can configure JAAS in CXF, and some of the JAAS LoginModules that are available.

1) Configuring JAAS in Apache CXF

There are a number of different ways to configure your CXF web service to authenticate tokens via JAAS. For all approaches, you must define the System property "java.security.auth.login.config" to point towards your JAAS configuration file.

1.1) JAASLoginInterceptor

CXF provides a interceptor called the JAASLoginInterceptor that can be added either to the "inInterceptor" chain of an endpoint (JAX-WS or JAX-RS) or a CXF bus (so that it applies to all endpoints). The JAASLoginInterceptor typically authenticates a Username/Password credential (such as a WS-Security UsernameToken or HTTP/BA) via JAAS. Note that for WS-Security, you must tell WSS4J not to authenticate the UsernameToken itself, but just to process it and store it for later authentication via the JAASLoginInterceptor. This is done by setting the JAX-WS property "ws-security.validate.token" to "false".

At a minimum it is necessary to set the "contextName" attribute of the JAASLoginInterceptor, which references the JAAS Context Name to use. It is also possible to define how to retrieve roles as part of the authentication process, by default CXF assumes that javax.security.acl.Group Objects are interpreted as "role" Principals. See the CXF wiki for more information on how to configure the JAASLoginInterceptor. After successful authentication, a CXF SecurityContext Object is created with the name and roles of the authenticated principal.

1.2) JAASAuthenticationFeature

Newer versions of CXF also have a CXF Feature called the JAASAuthenticationFeature. This simply wraps the JAASLoginInterceptor with default configuration for Apache Karaf. If you are deploying a CXF endpoint in Karaf, you can just add this Feature to your endpoint or Bus without any additional information, and CXF will authenticate the received credential to whatever Login Modules have been configured for the "karaf" realm in Apache Karaf.

1.3) JAASUsernameTokenValidator

As stated above, it is possible to validate a WS-Security UsernameToken in CXF via the JAASLoginInterceptor or the JAASAuthenticationFeature by first setting the JAX-WS property "ws-security.validate.token" to "false". This tells WSS4J to avoid validating UsernameTokens. However it is possible to also validate UsernameTokens using JAAS directly in WSS4J via the JAASUsernameTokenValidator. You can configure this validator when using WS-SecurityPolicy via the JAX-WS property "ws-security.ut.validator".

2) Using JAAS LoginModules in Apache CXF

Once you have decided how you are going to configure JAAS in Apache CXF, it is time to pick a JAAS LoginModule that is appropriate for your authentication requirements. Here are some examples of LoginModules you can use.

2.1) Validating a Username + Password to LDAP / Active Directory

For validating a Username + Password to an LDAP / Active Directory backend, use one of the following login modules:
  • com.sun.security.auth.module.LdapLoginModule: Example here (context name "sun").
  • org.eclipse.jetty.plus.jaas.spi.LdapLoginModule: Example here (context name "jetty"). Available via the org.eclipse.jetty/jetty-plus dependency. This login module is useful as it's easy to retrieve roles associated with the authenticated user.
2.2) Validating a Kerberos token

Kerberos tokens can be validated via:
  • com.sun.security.auth.module.Krb5LoginModule: Example here.
2.3) Apache Karaf specific LoginModules

Apache Karaf contains some LoginModules that can be used when deploying your application in Karaf:
  • org.apache.karaf.jaas.modules.properties.PropertiesLoginModule: Authenticates Username + Passwords and retrieves roles via "etc/users.properties".
  • org.apache.karaf.jaas.modules.properties.PublickeyLoginModule: Authenticates SSH keys and retrieves roles via "etc/keys.properties".
  • org.apache.karaf.jaas.modules.properties.OsgiConfigLoginModule: Authenticates Username + Passwords and retrieves roles via the OSGi Config Admin service.
  • org.apache.karaf.jaas.modules.properties.LDAPLoginModule: Authenticates Username + Passwords and retrieves roles from an LDAP backend.
  • org.apache.karaf.jaas.modules.properties.JDBCLoginModule:  Authenticates Username + Passwords and retrieves roles from a database.
  • org.apache.karaf.jaas.modules.properties.SyncopeLoginModule: Authenticates Username + Passwords and retrieves roles via the Apache Syncope IdM.
See Jean-Baptiste Onofré's excellent blog for a description of how to set up and test the SyncopeLoginModule. Note that it is also possible to use this LoginModule in other containers, see here for an example.

Thursday, October 9, 2014

New Apache WSS4J releases

Apache WSS4J 1.6.17 and 2.0.2 have been released. WSS4J 2.0.2 picks up some bug fixes via Apache Santuario and BouncyCastle dependency upgrades, in particular the latter upgrade fixes some Kerberos issues. Both releases contain some changes to how SAML tokens are processed that will be described in a forthcoming blog post.

I also added a new Security Advisories page to the WSS4J website. For the moment it just contains some links and information on downstream security advisories that might be relevant to users of WSS4J.

Wednesday, October 8, 2014

Some recent WS-Trust client topics in Apache CXF

There are a number of minor new features and changes in recent versions of Apache CXF with respect to the client side of WS-Trust, which will be documented in this post.

1) STSClient configuration

CXF's STSClient is responsible for communicating with a Security Token Service (STS) via the WS-Trust protocol, in order to issue/validate/renew/etc. a security token. To support WS-Trust on the client side in CXF, it is necessary to construct an STSClient instance, and then reference it via the JAX-WS property key "ws-security.sts.client". Here is a typical example in spring.

However, there are some alternatives to configuring an STSClient per JAX-WS client object (see the CXF documentation for additional information). Strictly speaking these alternatives have been available in previous versions of CXF, however some bugs were fixed in the latest releases to enable them to work properly:

a) If no STSClient is directly configured on the JAX-WS client, then the CXF runtime will look for an STSClient bean with a name that corresponds to the Endpoint name with the suffix ".sts-client". Here is an example:

<bean id="stsClient" class="org.apache.cxf.ws.security.trust.STSClient"
    name="{http://www.example.org/contract/DoubleIt}DoubleItTransportSAML1Port.sts-client"
    abstract="true"
>

b) If no STSClient is configured either directly on the client, or else via the approach given in (a) above, then the security runtime tries to fall back to a "default" client. All that is required here is that the name of the STSClient bean should be "default.sts-client". Here is an example:

<bean id="stsClient" class="org.apache.cxf.ws.security.trust.STSClient"
    name="default.sts-client"
    abstract="true"
>

2) Falling back to Issue after a failed Renew

When a cached SecurityToken is expired, the STSClient tries to renew the token. However, not all STS instances support the renewal binding of WS-Trust. Therefore a new configuration parameter was introduced:
  • SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW ("ws-security.issue.after.failed.renew") -  Whether to fall back to calling "issue" after failing to renew an expired token. The default is "true".
 3) Renewing security tokens that are "about to" expire

There is a potential issue when a cached security token is "about to" expire. The CXF client will retrieve the cached token + check to see whether the token is expired or not. If it is expired, then it renews the token. If the token is valid, then it uses it in the service request. However, if the security token expires "en route" to the service, then the service will reject the token, and the service invocation will fail.

In CXF 2.7.13 and 3.0.2, support has been added to forcibly renew tokens that are about to expire, rather than risk letting them expire en route. A new configuration parameter has been introduced:
  • SecurityConstants.STS_TOKEN_IMMINENT_EXPIRY_VALUE ("ws-security.sts.token.imminent-expiry-value") - The value in seconds within which a token is considered to be expired by the client, i.e. it is considered to be expired if it will expire in a time less than the value specified by this tag.
The default value for this parameter for CXF 3.0.2 is "10", meaning that if a security token will expire in less than 10 seconds, it will be renewed by the client. For CXF 2.7.13, the default value is "0" for backwards compatibility reasons, meaning that this functionality is disabled.