Colm O hEigeartaigh

An interop demo between Apache CXF Fediz and Keycloak

Colm O hEigeartaigh - Mon, 02/01/2016 - 17:15
Last week, I showed how to use the Apache CXF Fediz IdP as an identity broker with a real-world SAML SSO IdP based on the Shibboleth IdP (as opposed to an earlier article which used a mocked SAML SSO IdP). In this post, I will give similar instructions to configure the Fediz IdP to act as an identity broker with Keycloak.

1) Install and configure Keycloak

Download and install the latest Keycloak distribution (tested with 1.8.0). Start keycloak in standalone mode by running 'sh bin/standalone.sh'.

1.1) Create users in Keycloak

First we need to create an admin user by navigating to the following URL, and entering a password:
  • http://localhost:8080/auth/
Click on the "Administration Console" link, logging on using the admin user credentials. You will see the configuration details of the "Master" realm. For the purposes of this demo, we will create a new realm. Hover the mouse pointer over "Master" in the top left-hand corner, and click on "Add realm". Create a new realm called "realmb". Now we will create a new user in this realm. Click on "Users" and select "Add User", specifying "alice" as the username. Click "save" and then go to the "Credentials" tab for "alice", and specify a password, unselecting the "Temporary" checkbox, and reset the password.

1.2) Create a new client application in Keycloak

Now we will create a new client application for the Fediz IdP in Keycloak. Select "Clients" in the left-hand menu, and click on "Create". Specify the following values:
  • Client ID: urn:org:apache:cxf:fediz:idp:realm-A
  • Client protocol: saml
  • Client SAML Endpoint: https://localhost:8443/fediz-idp/federation
Once the client is created you will see more configuration options:
  • Select "Sign Assertions"
  • Select "Force Name ID Format".
  • Valid Redirect URIs: https://localhost:8443/*
Now go to the "SAML Keys" tab of the newly created client. Here we will have to import the certificate of the Fediz IdP so that Keycloak can validate the signed SAML requests. Click "Import" and specify:
  • Archive Format: JKS
  • Key Alias: realma
  • Store password: storepass
  • Import file: stsrealm_a.jks
1.3) Export the Keycloak signing certificate

Finally, we need to export the Keycloak signing certificate so that the Fediz IdP can validate the signed SAML Response from Keycloak. Select "Realm Settings" (for "realmb") and click on the "Keys" tab. Copy and save the value specified in the "Certificate" textfield.

2) Install and configure the Apache CXF Fediz IdP and sample Webapp

Follow a previous tutorial to deploy the latest Fediz IdP + STS to Apache Tomcat, as well as the "simpleWebapp". Test that the "simpleWebapp" is working correctly by navigating to the following URL (selecting "realm A" at the IdP, and authenticating as "alice/ecila"):
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
2.1) Configure the Fediz IdP to communicate with Keycloak

Now we will configure the Fediz IdP to authenticate the user in "realm B" by using the SAML SSO protocol. Edit 'webapps/fediz-idp/WEB-INF/classes/entities-realma.xml'. In the 'idp-realmA' bean:
  • Change the port in "idpUrl" to "8443". 
In the 'trusted-idp-realmB' bean:
  • Change the "url" value to "http://localhost:8080/auth/realms/realmb/protocol/saml".
  • Change the "protocol" value to "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser".
  • Change the "certificate" value to "keycloak.cert".
2.2) Configure Fediz to use the Keycloak signing certificate

Copy 'webapps/fediz-idp/WEB-INF/classes/realmb.cert' to a new file called 'webapps/fediz-idp/WEB-INF/classes/keycloak.cert'. Edit this file + delete the content between the "-----BEGIN CERTIFICATE----- / -----END CERTIFICATE-----" tags, pasting instead the Keycloak signing certificate as retrieved in step "1.3" above.

The STS also needs to trust the Keycloak signing certificate. Copy keycloak.cert into 'webapps/fediz-idp-sts/WEB-INF/classes". In this directory import the keycloak.cert into the STS truststore via:
  • keytool -keystore ststrust.jks -import -file keycloak.cert -storepass storepass -alias keycloak
Restart Fediz to pick up the changes (you may need to remove the persistent storage first).

3) Testing the service

To test the service navigate to:
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
Select "realm B". You should be redirected to the Keycloak authentication page. Enter the user credentials you have created. You will be redirected to Fediz, where it converts the received SAML token to a token in the realm of Fediz (realm A) and redirects to the web application.


Categories: Colm O hEigeartaigh

An interop demo between Apache CXF Fediz and Shibboleth

Colm O hEigeartaigh - Tue, 01/26/2016 - 12:45
Apache CXF Fediz is an open source implementation of the WS-Federation Passive Requestor Profile for SSO. It allows you to configure SSO for your web application via a container plugin, which redirects the user to authenticate at an IdP (Fediz or another WS-Federation based IdP). The Fediz IdP also supports the ability to act as an identity broker to a remote IdP, if the user is to be authenticated in a different realm. Last year, this blog covered a new feature of Apache CXF Fediz 1.2.0, which was the ability to act as an identity broker with a remote SAML SSO IdP. In this post, we will look at extending the demo to work with the Shibboleth IdP.

1) Install and configure the Apache CXF Fediz IdP and sample Webapp

Firstly, follow a previous tutorial to deploy the latest Fediz IdP + STS to Apache Tomcat, as well as the "simpleWebapp". Test that the "simpleWebapp" is working correctly by navigating to the following URL (selecting "realm A" at the IdP, and authenticating as "alice/ecila"):
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
Now we will configure the Fediz IdP to authenticate the user in "realm B", by using the SAML SSO protocol with a Shibboleth IdP instance. Edit 'webapps/fediz-idp/WEB-INF/classes/entities-realma.xml':

In the 'idp-realmA' bean:
  • Change the port in "idpUrl" to "8443". 
In the 'trusted-idp-realmB' bean:
  • Change the "url" value to "http://localhost:9080/idp/profile/SAML2/Redirect/SSO".
  • Change the "protocol" value to "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser".
  • Add the following property: <property name="parameters"><util:map><entry key="require.known.issuer" value="false" /></util:map></property>
Restart Fediz to pick up the changes (you may need to remove the persistent storage first).

2) Install and configure Shibboleth

This is a reasonable complex task, so let's break it down into various sections.

2.1) Install Shibboleth and deploy to Tomcat

Download and extract the latest Shibboleth Identity Provider (tested with 3.2.1). Install Shibboleth by running the "install.sh" script in the bin directory. Install Shibboleth to "$SHIB_HOME" and use the default values that are prompted as part of the installation process, entering a random password for the keystore (we won't be using it). Download and extract an Apache Tomcat 7 instance, and follow these steps:
  • Copy '$SHIB_HOME/war/idp.war' into the Tomcat webapps directory.
  • Configure Shibboleth to find the IDP by defining: export JAVA_OPTS="-Xmx512M -Didp.home=$SHIB_HOME".
  • Next you need to download the jstl jar (https://repo1.maven.org/maven2/jstl/jstl/1.2/) + put it in the lib directory of Tomcat.
  • Edit conf/server.xml + change the ports to avoid conflict with the Tomcat instance that the Fediz IdP is running in. (e.g. use 9080 instead of 8080, etc.).
  • Now start Tomcat + check that everything is working by navigating to: http://localhost:9080/idp/profile/status
2.2) Configure the RP provider in Shibboleth

Next we need to configure the Fediz IdP as a RP (relying party) in Shibboleth. The Fediz IdP has the ability to generate metadata (either WS-Federation or SAML SSO) for a trusted IdP. Navigate to the following URL in a browser and save the metadata to a local file "fediz-metadata.xml":
  • https://localhost:8443/fediz-idp/metadata/urn:org:apache:cxf:fediz:idp:realm-B
Edit '$SHIB_HOME/conf/metadata-providers.xml' and add the following configuration to pick up this metadata file:

<MetadataProvider id="FedizMetadata"  xsi:type="FilesystemMetadataProvider" metadataFile="$METADATA_PATH/fediz-metadata.xml"/>

As we won't be encrypting the SAML response in this demo, edit the '$SHIB_HOME/idp.properties' file and uncomment the "idp.encryption.optional = false" line, changing "false" to "true".

2.3) Configuring the Signing Keys in Shibboleth

Next we need to copy the keys that Fediz has defined for "realm B" to Shibboleth. Copy the signing certificate "realmb.cert" from the Fediz source and rename it as '$SHIB_HOME/credentials/idp-sigining.crt'. Next we need to extract the private key from the keystore and save it as a plaintext private key. Download the realmb keystore. Extract the private key via:
  • keytool -importkeystore -srckeystore stsrealm_b.jks -destkeystore stsrealmb.p12 -deststoretype PKCS12 -srcalias realmb -deststorepass storepass -srcstorepass storepass -srckeypass realmb -destkeypass realmb
  • openssl pkcs12 -in stsrealmb.p12  -nodes -nocerts -out idp-signing.key
  • Edit idp-signing.key to remove any additional information before the "BEGIN PRIVATE KEY" part.
  • cp idp-signing.key $SHIB_HOME/credentials
2.4) Configure Shibboleth to authenticate users

Next we need to configure Shibboleth to authenticate users. If you have a configured KDC or LDAP installation on your machine, then it is easiest to use this, if you configure some test users there. If not then, in this section we will configure Shibboleth to use JAAS to authenticate users via Kerberos. Edit '$SHIB_HOME/conf/authn/password-authn-config.xml' + comment out the ldap import, instead uncommenting the "jaas-authn-config.xml" import. Next edit '$SHIB_HOME/conf/authn/jaas.config' and replace the contents with:

 ShibUserPassAuth {
    com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=false;
};

Now we will set up and configure a test KDC. Assuming you are running this demo on linux, edit '/etc/krb5.conf' and change the "default_realm" to "service.ws.apache.org" + add the following to the realms section:

        service.ws.apache.org = {
                kdc = localhost:12345
        }

Now we will look at altering a test-case I wrote that uses Apache Kerby as a test-kdc. Clone my testcases github repo and go to the "cxf-kerberos-kerby" test-case, which is part of the top level "cxf" projects. Edit the AuthenticationTest
and change the values for KDC_PORT + KDC_UDP_PORT to "12345". Next remove the @org.junit.Ignore annotation from the "launchKDCTest()" method to just launch the KDC + sleep for a few minutes. Launch the test on the command line via "mvn test -Dtest=AuthenticationTest".

2.5) Configure Shibboleth to include the authenticated principal in the SAML Subject

For the purposes of our demo scenario, the Fediz IdP expects the authenticated principal in the SAML Subject it gets back from Shibboleth. Edit '$SHIB_HOME/conf/attribute-filter.xml' and add the following:

    <AttributeFilterPolicy id="releasePersistentIdToAnyone">
        <PolicyRequirementRule xsi:type="ANY"/>

        <AttributeRule attributeID="persistentId">
            <PermitValueRule xsi:type="ANY"/>
        </AttributeRule>
    </AttributeFilterPolicy>

Edit '$SHIB_HOME/conf/attribute-resolver.xml' and add the following:

<resolver:AttributeDefinition id="persistentId" xsi:type="ad:PrincipalName">
      <resolver:AttributeEncoder xsi:type="enc:SAML1StringNameIdentifier" nameFormat="urn:mace:shibboleth:1.0:nameIdentifier"/>
      <resolver:AttributeEncoder xsi:type="enc:SAML2StringNameID" nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
</resolver:AttributeDefinition>

Edit '$SHIB_HOME/conf/saml-nameid.xml' and comment out any beans listed in the "shibboleth.SAML2NameIDGenerators" list. Finally, edit '$SHIB_HOME/conf/saml-nameid.properties' and uncomment the legacy Generator:

idp.nameid.saml2.legacyGenerator = shibboleth.LegacySAML2NameIDGenerator

That will enable Shibboleth to process the "persistent" attribute using the Principal Name. (Re)start the Tomcat instance we we should be ready to go.

3) Testing the service

To test the service navigate to:
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
Select "realm B". You should be redirected to the Shibboleth authentication page. Enter "alice/alice" as the username/password. You will be redirected to Fediz, where it converts the received SAML token to a token in the realm of Fediz (realm A) and redirects to the web application.




Categories: Colm O hEigeartaigh

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

Colm O hEigeartaigh - Mon, 12/07/2015 - 18:03
This is the third article in a series of posts on support for Javascript Object Signing and Encryption (JOSE) in Apache CXF. The previous article described how to encrypt content using the JSON Web Encryption specification. This post covers support for JSON Web Tokens (JWT) in Apache CXF. The JWT spec is not strictly part of the JOSE specification set, but it makes sense to cover it in this series of posts, as it is a natural extension of the JOSE specs to convey claims.

1) Test Cases:

As before, let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code first constructs a JWT Token and then includes it in the message payload by adding a specific provider. The JWT Token is then processed by a provider on the receiving side. We will cover the individual tests in more detail below.

2) Constructing JWT Tokens

Apache CXF provides an easy to use API to create JWT Tokens. Let's look at how this is done in one of the tests - the JWTAuthenticationTest. The tests construct a JwtClaims Object, which has convenient set/get methods for the standard JWT Claims. For example:


The JwtClaims Object can be passed through to the constructor of a JwtToken Object. To serialize the JwtToken in the request simply add the JwtAuthenticationClientFilter to the client provider list, and specify the JwtToken Object as a message property under "jwt.token". Alternatively, the JwtClaims Object can be passed without having to construct a JwtToken via the property "jwt.claims". On the receiving side, a JWTToken can be processed by the JwtAuthenticationFilter provider.

3) Authentication and Authorization using signed JWT Tokens

By default, the JwtAuthenticationClientFilter signs the JWT Token. The signature configuration is the exact same as that used for JWS as covered in the first article. On the receiving side, the JwtAuthenticationFilter will set up a security context for the authenticated client, assuming that a public key signature algorithm was used to sign the token. The "sub" (Subject) claim from the token gets mapped to the principal of the security context.

As the JWT Token can convey arbitrary claims, it can be used for RBAC authorization. This is demonstrated in the JWTAuthorizationTest. A role called "boss" is inserted into the token. On the receiving side, the JwtAuthenticationFilter is configured to use the "role" claim in the token to extract roles for the authenticated principal and to populate the security context with them. As part of the test-case, CXF's SimpleAuthorizingInterceptor is used to require that a client must have a role of "boss" to invoke on the web service method in question.

4) Encrypting JWT Tokens

It is very easy to encrypt JWT Tokens (as well as both sign and encrypt) them in CXF. The JwtAuthenticationClientFilter needs to be configured to also encrypt the token, and the same configuration is used as for JWE in the previous article. Similarly, on the receiving side the JwtAuthenticationFilter must have the property "jweRequired" set to "true" to decrypt incoming encrypted tokens. See the JWTEncryptedTest test for some examples. 

5) Token validation

On receiving a JAX-RS request containing a JWT token, the
JwtAuthenticationFilter will first parse the token, and then verify the signature (if present) and decrypt the token (if encrypted). It then performs some quality of service validation on the token claims, which I'll detail here. This validation can be easily modified by overriding the protected "validateToken" method in JwtAuthenticationFilter.
  • The "exp" (Expiration Time) claim is validated if present. If the expiry value is before the current date/time, then the token is rejected. 
  • The "nbf" (Not Before) claim is validated if present. If the not before value is after the current date/time, then the token is rejected. 
  • The "iat" (Issued At) claim is validated if present. To validate the "iat" claim, a "ttl" property must be set on the JwtAuthenticationFilter.
  • Either an "iat" or "exp" claim must be present in the token, as otherwise we have no way of enforcing an expiry on a token.
  • A clockskew value can also be configured on the JwtAuthenticationFilter via the "clockOffset" property.
  • The "aud" (Audience) claim is validated. This claim must contain at least one audience value which matches the endpoint address of the recipient.
Categories: Colm O hEigeartaigh

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

Colm O hEigeartaigh - Wed, 12/02/2015 - 18:49
This is the second in a series of blog posts on the support for the Javascript Object Signing and Encryption (JOSE) specifications in Apache CXF. The first article covered how to sign content using the JSON Web Signature (JWS) specification. In this post we will look at how to encrypt content using the JSON Web Encryption (JWE) specification.

1) Test Cases:

As before, let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
For now let's look at the tests contained in JWETest. These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code uses the CXF WebClient API to encrypt the message payload by adding a specific provider. The message in turn is decrypted by a provider on the receiving side. You can run the test via the command line "mvn test -Dtest=JWETest", and the message requests and responses will appear in the console.

2) Compact vs. JSON Serialization

Just like the JWS specification, there are two different ways of serializing JWE structures. Compact serialization is a URL-safe representation that is convenient to use when you only have a single encrypting entity. JSON serialization respresents the JWE structures as JSON objects. As of the time of publishing this post, CXF only has interceptors for the compact approach. However I'm told the JSON serialization case will be supported very soon :-)

The providers to use for the compact case on both the client + receiving sides are:
  • Compact: JweWriterInterceptor (out) + JweContainerRequestFilter (in)
3) Security Configuration

As well as adding the desired providers, it is also necessary to specify the security configuration to set the appropriate algorithms, keys, etc. to use. The CXF wiki has an extensive list of all of the different security configuration properties. For encryption, we need to first load the encrypting key (either a JKS keystore or else a JSON Web Key (JWK) is supported).

As well as defining the encryption key, we also need to configure the algorithms to encrypt the content as well as to encrypt the key. The list of acceptable encryption algorithms for JWE is defined by the JSON Web Algorithms (JWA) spec. For content encryption, the supported algorithms are all based on AES (CBC/GCM mode) with different key sizes. For key encryption, various schemes based on RSA, AES KeyWrap/GCM, Elliptic Curve Diffie-Hellman, PBES2 are supported, as well as a symmetric encryption option.

For example, the tests use the following configuration to load a public key from a Java KeyStore, and to use the RSA-OAEP key encryption algorithm, as well as a 128-bit AES content encryption algorithm in CBC mode, using HMAC-SHA256 to generate the authentication code:
The service side configuration is largely the same, apart from the fact that we need to specify the "rs.security.key.password" configuration tag to load the private key. The encryption algorithms must also be specified to impose a constraint on the desired algorithms.

4) Encrypting XML payload

Similar to the signature case, it is possible to use JWE to encrypt an XML message, and not just a JSON message. An example is included in JWETest ("testEncryptingXMLPayload").  The configuration is exactly the same as for the JSON case. 

5) Including the encrypting key

It is possible to include the encrypting certificate/key in the JWE header by setting one of the following properties:
  • rs.security.encryption.include.public.key - Include the JWK public key for encryption in the "jwk" header.
  • rs.security.encryption.include.cert - Include the X.509 certificate for encryption in the "x5c" header.
  • rs.security.encryption.include.key.id - Include the JWK key id for encryption in the "kid" header.
  • rs.security.encryption.include.cert.sha1 - Include the X.509 certificate SHA-1 digest for encryption in the "x5t" header.
It could be useful to include the encrypting certificate/key if the recipient has multiple decryption keys and doesn't know which one to use to decrypt the request.

6) Signing + encrypting a message

It is possible to both sign and encrypt a message by combining the JWS + JWE interceptors. For example, simply adding the JweWriterInterceptor and JwsWriterInterceptor providers on the client side will both sign and encrypt the request. An example is included in the github project above (JWEJWSTest). 
Categories: Colm O hEigeartaigh

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

Colm O hEigeartaigh - Mon, 11/30/2015 - 18:39
The Javascript Object Signing and Encryption (JOSE) specifications cover how to sign and encrypt data using JSON. Apache CXF has excellent support for all of the JOSE specifications (see the documentation here), thanks largely to the work done by my colleague Sergey Beryozkin. This is the first in a series of blog posts describing how to use and implement JOSE for your web services using Apache CXF. In this post, we will cover how to sign content using the JSON Web Signature (JWS) specification.

1) Test Cases:

Let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
For now let's look at the JWSSignatureTest. These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code uses the CXF WebClient API to sign the message payload by adding a specific provider. The message in turn is validated by a provider on the receiving side. You can run the test via the command line "mvn test -Dtest=JWSSignatureTest", and the message requests and responses will appear in the console.

For example, here is the output of the "testSignatureCompact" request. The Payload consists of the concatenated (+ separated by a '.') BASE-64 URL encoded JWS header (e.g. containing the signature algorithm, amongst other values), the BASE-64 URL encoded message payload, and the BASE-64 URL encoded signature value.


2) Compact vs. JSON Serialization

The JWS specification defines two different ways of serializing the signatures. Compact serialization is a URL-safe representation that is convenient to use when you only have a single signing entity. JSON serialization resprents the JWS structures as JSON objects, and allows multiple signatures to be included in the request as a result. The JWSSignatureTest includes both examples ("testSignatureListProperties" and "testSignatureCompact"). It's very easy to experiment with both approaches, as you only have to use different providers on both the client + receiving sides:
  • JSON Serialization: JwsJsonWriterInterceptor (out) + JwsJsonContainerRequestFilter (in)
  • Compact: JwsWriterInterceptor (out) + JwsContainerRequestFilter (in)
3) Security Configuration

As well as adding the desired providers, it is also necessary to specify the security configuration to set the appropriate algorithms, keys, etc. to use. The CXF wiki has an extensive list of all of the different security configuration properties. For signature, we need to first load the signing key (either a JKS keystore or else a JSON Web Key (JWK) is supported).

As well as defining a signing key, we also need to configure the signing algorithm. The list of acceptable signing algorithms for JWS is defined by the JSON Web Algorithms (JWA) spec. For signature, this boils down to a public key signature scheme based on either RSA or EC-DSA, or a symmetric scheme using HMAC.

For example, the tests use the following configuration to load a private key from a Java KeyStore, and to use the signature scheme of RSASSA-PKCS1-v1_5 using SHA-256:
The service side configuration is largely the same, apart from the fact that we don't need to specify the "rs.security.key.password" configuration tag, as we don't need to load the private key. The signature algorithm must be specified to impose a constraint on the acceptable signature algorithm.

4) Signing XML payload

The JWS payload (the content to be signed) can be any binary content and not just a JSON Object. This means that we can use JWS to sign an XML message. This is a really cool feature of the specification in my opinion, as it essentially removes the need to use XML Signature to sign XML payload. An example of this is included in the JWSSignatureTest. The configuration is exactly the same as for the JSON case.

5) Including the signing key

It is possible to include the signing certificate/key in the JWS header by setting one of the following properties:
  • rs.security.signature.include.public.key -  Include the JWK public key for signature in the "jwk" header.
  • rs.security.signature.include.cert - Include the X.509 certificate for signature in the "x5c" header.
  • rs.security.signature.include.key.id - Include the JWK key id for signature in the "kid" header.
  • rs.security.signature.include.cert.sha1- Include the X.509 certificate SHA-1 digest for signature in the "x5t" header.
One advantage of including the entire certificate is that the service doesn't need to store the client certificate locally, but only the issuing certificate.
Categories: Colm O hEigeartaigh

New security advisory for Apache CXF

Colm O hEigeartaigh - Mon, 11/16/2015 - 13:28
A new security advisory has been released for Apache CXF, which is fixed in the 3.1.3, 3.0.7 and 2.7.18 releases.
  • CVE-2015-5253: Apache CXF SAML SSO processing is vulnerable to a wrapping attack
Apache CXF supports the SAML SSO protocol with JAX-RS web service endpoints. It is possible for a malicious user to construct a SAML Response (the response from the SAML SSO IdP to the endpoint) via a so-called "wrapping attack", to allow that user to log in instead of the authenticated user associated with the signed SAML Assertion.

Please see the Apache CXF security advisories page for more information.
Categories: Colm O hEigeartaigh

Testing Kerberos with Web Services using Apache Kerby

Colm O hEigeartaigh - Wed, 11/11/2015 - 13:13
The previous blog post described how to use Apache Directory to easily create a KDC via Java annotations for kerberos integration testing. In this post, we will look at an alternative way of setting up a KDC for integration testing using Apache Kerby.

Apache Kerby is a new subproject of Apache Directory that aims to provide a complete Kerberos solution in Java. Version 1.0.0-RC1 has recently been released and is available for testing. Apache Kerby consists of both a KDC as well as a client API, that is completely independent of the GSS API that comes with Java. A key selling point of Apache Kerby is that it is very easy and fast to setup and deploy a KDC. It is possible to set up a KDC completely in code, without having to edit any configuration files or configure any system properties.

Let's see how this is done by looking at a project I created on github:
  • cxf-kerberos-kerby: This project contains a number of tests that show how to use Kerberos with Apache CXF, where the KDC used in the tests is based on Apache Kerby.
The KDC is launched in the test-code, and is pretty much as straightfoward as the following code snippet:

The first block of code configures the host, realm, transports and ports, while the second creates the client, service and TGT principals that are used in the tests. No configuration files required! As well as showing how to use Apache CXF to authenticate using both Kerberos and Spnego for a JAX-WS service, the AuthenticationTest also includes unit tests for getting a service ticket from the Kerby KDC using the Java GSS API as well as the Kerby client API. Using the Kerby client API is as simple as this:


Have fun playing around with Apache Kerby and please join and contribute to the project if you are interested!
Categories: Colm O hEigeartaigh

Testing Kerberos with Web Services using Apache Directory

Colm O hEigeartaigh - Mon, 10/26/2015 - 12:59
Apache CXF supports Kerberos for web services both via the Kerberos Token Profile of WS-Security, where the kerberos ticket is conveyed as a BinarySecurityToken in the security header of the client request, and over HTTP via the Negotiate authentication scheme. If you are developing kerberos-enabled web services using a framework like Apache CXF, a natural question to ask is how to set up a Kerberos KDC to test your web services prior to deployment. This is the first of two blog posts that shows two different ways to easily set up a KDC using open source projects for kerberos integration testing.

At ApacheCon EU 2014 in Budapest, I attended a great talk by Emmanuel Lécharny entitled "Testing LDAP Implementations". The talk covered how the Apache Directory project can be used to easily deploy Kerberos and LDAP servers in your test-code via annotations. This was music to my ears, as I had written a bunch of tests in Apache CXF for both LDAP and kerberos that were not run as part of the normal build, as they required a local KDC to run successfully. After this talk I got involved in the Apache Directory project, and converted the tests in Apache CXF to use Apache Directory instead, so they could be run as part of the normal build cycle. I also made some small improvements which I'll describe as part of this post.

I've created a project in github that shows how to use Apache Directory to set up a KDC, and how to use Apache CXF to authenticate to a web service using Kerberos, for both JAX-RS and JAX-WS:
  • cxf-kerberos: This project contains a number of tests that show how to use Kerberos with Apache CXF.
Both test-cases use an annotation to load a kerberos.ldif file, containing the information required to set up Kerberos principals in the KDC for testing:


 Another annotation sets up the Directory Service:

Finally, an annotation adds a KDC server:

The "KRB" protocol was added as part of DIRSERVER-2031 in the 2.0.0-M20 release. Previously, you could specify either "TCP" or "UDP" for the protocol attribute when testing Kerberos. However, this meant that they could not share the same port. The "KRB" protocol generates both TCP and UDP transports on the port provided, or otherwise on a random port. Previously, the random port generation was not working, as it always defaulted to 1024. Random port generation is an essential feature for testing as part of a build cycle, as hard-coded ports tend to cause problems on continuous integration platforms. Using a random port also means that the krb5.conf file used by the CXF clients must be read in, and the random port substituted into the file before writing it out again, as otherwise the clients would have no way of knowing the port the KDC was running on.
Categories: Colm O hEigeartaigh

A certificate revocation security vulnerability in Java

Colm O hEigeartaigh - Fri, 10/23/2015 - 12:04
A few days ago, Oracle released a Critical Patch Update containing fixes for various security vulnerabilities. In particular, the update contained fixes for 25 security vulnerabilities in Java itself. One of them, CVE-2015-4868, was discovered by me and duly disclosed to Oracle earlier this year. This issue has now been fixed in this Critical Patch Update (and included in Java 1.8.0_65), and so I am free to describe it.

1) Background

I first noticed this issue in the context of signature validation of SOAP web service requests. A signed SOAP request involves using XML Signature to sign some part of the request, where the resulting Signature structure is inserted into the security header of the request. The Signature contains a KeyInfo Element, which references the (public) key to use to validate the request. The recipient must resolve the appropriate public key, establish trust in it, and use it to validate the signature.

A common use-case is when the certificate used to validate the signature is included directly in the request, by BASE-64 encoding it in the security header. Optionally, the full certificate chain can be included instead. The recipient must take the certificates and establish a trust chain using a CA certificate stored in a local truststore, which is then validated.

However, what if the signing certificate has been revoked by the issuing CA? In this case, we can specify a Certificate Revocation List, and include it as part of the validation of the trust chain.

2) The vulnerability

Now to the vulnerability. Under the more usual use-case of just including the signing certificate in the security header, and establishing a trust-chain using a local truststore and CRL file, everything was working fine. Namely, if the signing certificate was trusted, but revoked, then the CertPath validation failed. However, if the issuing certificate of the signing certificate was also included in the security header, then CRL validation was not failing! This vulnerability exists in a range of JDK 8 versions prior to 1.8.0_65. It does not exist prior to JDK 8.

To see how this works using the Java CertPathValidator API, I created a simple maven-based unit test in github:
  • java.crls - A testcase that show how to include a CRL when validating the certificate path of a certificate.
The test has a JUnit failure assertion that asserts that the CertPathValidator validation should fail (as the signing certificate has been revoked). However, this failure assertion is not met when run locally with Java 1.8.0_51. With a Java version post-1.8.0_65 the failure assertion is met, and the test passes.
Categories: Colm O hEigeartaigh

Support for Jetty 9 in Apache CXF Fediz 1.3.0

Colm O hEigeartaigh - Fri, 09/18/2015 - 18:31
Yesterday I gave a tutorial on how to deploy the Apache CXF Fediz simpleWebapp example to Jetty 8 using Fediz 1.2.1. Apache CXF Fediz 1.3.0 will ship with a new plugin to support Jetty 9. In this post I will cover how to deploy the simpleWebapp example to Jetty 9 using this new plugin.

1) Deploying the 1.2.0 Fediz IdP in Apache Tomcat

As per the previous tutorial on deploying to Tomcat, we will deploy the IdP and STS in Apache Tomcat. Download Fediz and extract it to a new directory (${fediz.home}). To deploy the IdP to Tomcat:

  • Copy ${fediz.home}/idp/war/* to ${catalina.home}/webapps
  • Download and copy the hsqldb jar (e.g. hsqldb-1.8.0.10.jar) to ${catalina.home}/lib
  • Copy idp-ssl-key.jks and idp-ssl-trust.jks from ${fediz.home}/examples/samplekeys to ${catalina.home}.
  • Edit ${catalina.home}/conf/server.xml and change the ports from 8080 -> 9080 + 8443 -> 9443 so as not to conflict with Jetty.
  • Edit the TLS Connector in ${catalina.home}/conf/server.xml' as well, e.g.: <Connector port="9443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="want" sslProtocol="TLS" keystoreFile="idp-ssl-key.jks" keystorePass="tompass" keyPass="tompass" truststoreFile="idp-ssl-trust.jks" truststorePass="ispass" />
Now start Tomcat, and check that the IdP is live by opening the STS WSDL in a web browser: 'https://localhost:9443/fediz-idp-sts/REALMA/STSServiceTransport?wsdl'

2) Deploying the simpleWebapp in Jetty 9

Download Jetty 9 and extract it to a new directory (${jetty.home}). First let's set up TLS:
  • Copy ${fediz.home}/examples/samplekeys/rp-ssl-key.jks to ${jetty.home}/etc
  • Copy ${fediz.home}/examples/samplekeys/ststrust.jks to ${jetty.home} *and* to ${jetty.home}/etc
  • Edit ${jetty.home}/start.ini to include the ssl, https and fediz modules, and set up the TLS configuration as follows:
  •  The "fediz" module referred to above must be placed in ${jetty.home}/modules/fediz.mod with content:
Now we will deploy the simpleWebapp:
  • Copy ${fediz.home}/examples/simpleWebapp/src/main/config/fediz_config.xml to ${jetty.home}/etc
  • Do a "mvn clean install" in ${fediz.home}/examples/simpleWebapp
  • Copy ${fediz.home}/examples/simpleWebapp/target/fedizhelloworld.war to ${jetty.home}/webapps
  • Create a new directory: ${jetty.home}/lib/fediz
  • Copy ${fediz.home}/plugins/jetty9/lib/* to ${jetty.home}/lib/fediz (note you may want to copy in a slf4j logging binding in here to see logging output, e.g. slf4j-jdk14-1.7.12.jar).
  • Create a new file in ${jetty.home}/webapps called "fedizhelloworld.xml" with content as follows, and then start Jetty as normal: 

3) Testing the service

To test the service navigate to:
  • https://localhost:8443/fedizhelloworld/  (this is not secured) 
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
With the latter URL, the browser is redirected to the IDP (select realm "A") and is prompted for a username and password. Enter "alice/ecila" or "bob/bob" or "ted/det" to test the various roles that are associated with these username/password pairs.
Categories: Colm O hEigeartaigh

Deploying the Apache CXF Fediz simpleWebapp to Jetty

Colm O hEigeartaigh - Thu, 09/17/2015 - 18:41
On previous tutorials about Apache CXF Fediz, I have always described deploying the simpleWebapp example that ships with Fediz in Apache Tomcat. However, Fediz also supports deploying secured applications in Jetty (7 and 8 as of yet, support for Jetty 9 is forthcoming). As it can be somewhat confusing setting up the security requirements correctly, I will cover briefly how to deploy the simpleWebapp in Jetty 8 in this blog post (see the Fediz wiki for a dedicated page on deploying to Jetty).

1) Deploying the 1.2.0 Fediz IdP in Apache Tomcat

As per the previous tutorial on deploying to Tomcat, we will deploy the IdP and STS in Apache Tomcat. Download Fediz 1.2.1 and extract it to a new directory (${fediz.home}). To deploy the IdP to Tomcat:
  • Copy ${fediz.home}/idp/war/* to ${catalina.home}/webapps
  • Download and copy the hsqldb jar (e.g. hsqldb-1.8.0.10.jar) to ${catalina.home}/lib
  • Copy idp-ssl-key.jks and idp-ssl-trust.jks from ${fediz.home}/examples/samplekeys to ${catalina.home}.
  • Edit ${catalina.home}/conf/server.xml and change the ports from 8080 -> 9080 + 8443 -> 9443 so as not to conflict with Jetty.
  • Edit the TLS Connector in ${catalina.home}/conf/server.xml' as well, e.g.: <Connector port="9443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="want" sslProtocol="TLS" keystoreFile="idp-ssl-key.jks" keystorePass="tompass" keyPass="tompass" truststoreFile="idp-ssl-trust.jks" truststorePass="ispass" />
Now start Tomcat, and check that the IdP is live by opening the STS WSDL in a web browser: 'https://localhost:9443/fediz-idp-sts/REALMA/STSServiceTransport?wsdl'

2) Deploying the simpleWebapp in Jetty 8

Download Jetty 8 and extract it to a new directory (${jetty.home}). First let's set up TLS:
  • Copy ${fediz.home}/examples/samplekeys/rp-ssl-key.jks to ${jetty.home}/etc
  • Copy ${fediz.home}/examples/samplekeys/ststrust.jks to ${jetty.home} *and* to ${jetty.home}/etc
  • Edit ${jetty.home}/start.ini and make sure that 'etc/jetty-ssl.xml' is included.
  • Edit ${jetty.home}/etc/jetty-ssl.xml and configure the TLS keys, e.g.:


Now we will deploy the simpleWebapp:
  • Copy ${fediz.home}/examples/simpleWebapp/src/main/config/fediz_config.xml to ${jetty.home}/etc
  • Do a "mvn clean install" in ${fediz.home}/examples/simpleWebapp
  • Copy ${fediz.home}/examples/simpleWebapp/target/fedizhelloworld.war to ${jetty.home}/webapps
  • Create a new directory: ${jetty.home}/lib/fediz
  • Copy ${fediz.home}/plugins/jetty/lib/* to ${jetty.home}/lib/fediz (note you may want to copy in a slf4j logging binding in here to see logging output, e.g. slf4j-jdk14-1.7.12.jar).
  • Edit ${jetty.home}/start.ini and add "fediz" to "OPTIONS".
  • Create a new file in ${jetty.home}/contexts called "fedizhelloworld.xml" with content as follows, and then start Jetty as normal:

3) Testing the service

To test the service navigate to:
  • https://localhost:8443/fedizhelloworld/  (this is not secured) 
  • https://localhost:8443/fedizhelloworld/secure/fedservlet
With the latter URL, the browser is redirected to the IDP (select realm "A") and is prompted for a username and password. Enter "alice/ecila" or "bob/bob" or "ted/det" to test the various roles that are associated with these username/password pairs.
    Categories: Colm O hEigeartaigh

    Authorization for web services using XACML 3.0

    Colm O hEigeartaigh - Tue, 09/08/2015 - 16:29
    In a blog post last year, I covered some authentication and authorization test-cases for Apache CXF-based web services that I uploaded to github. In particular, the cxf-sts-xacml demo showed how a CXF service can use XACML to authorize a web service request, by sending a XACML request to a Policy Decision Point (PDP) and then by enforcing the authorization decision. This demo only covered XACML 2.0 (provided by OpenSAML). In this post we will give an example of how to use XACML 3.0 via Apache OpenAz to make and enforce authorization requests for Apache CXF based services.

    1) Introducing Apache OpenAz

    The XACML functionality in Apache CXF is based on OpenSAML, which provides support for XACML 2.0. However, XACML 3.0 is an OASIS standard as of January, 2013. A new project in the Apache Incubator called Apache OpenAz addresses this gap. The source code is broken down into the following modules:
    • openaz-xacml - API + common functionality.
    • openaz-xacml-rest - Some common functionality used by the RESTful API interfaces
    • openaz-xacml-pdp - A PDP implementation
    • openaz-xacml-pdp-rest - An implementation of the XACML 3.0 RESTful Interface for the PDP
    • openaz-xacml-pap-rest - An implementation of the XACML 3.0 RESTful Interface for the PAP
    • openaz-xacml-test - Some testsuites
    • openax-pep -  The PEP (Policy Enforcement Point) implementation.
    2) Integrating Apache OpenAz with Apache CXF

    The testcases are available here:
    • cxf-sts-xacml: This project contains a number of tests that show how to use XACML with CXF to authorize a client request. It contains both XACML 2.0 tests and XACML 3.0 tests.
    In both cases, the client obtains a SAML Token from the STS with the roles of the client embedded in the token. The service provider extracts the roles, and creates a XACML request. For the XACML 2.0 case, OpenSAML is used to create a XML XACML 2.0 request. This is then sent to a mocked PDP JAX-RS service. However, let's focus on the XACML 3.0 case. In this test, the OpenAz API (via the openaz-xacml module as covered above) is used to create a JSON XACML 3.0 request. This is evaluated by a OpenAz-based PDP which is co-located with the service. After evaluating the request, the PDP response is then enforced at the service side.

    The service endpoint is configured in Spring as follows, registering a XACML3AuthorizingInterceptor (which in turn contains a reference to the co-located PDP):

    The XACML3AuthorizingInterceptor is configured with a implementation to create a XACML 3.0 request using the SAML 2.0 profile of XACML 3.0, which is subsequently converted into JSON + sent to the PDP. The PDP is configured with "root" and "reference" policies, that state that a user of role "boss" has permission to "execute" the Web Service Operation "{http://www.example.org/contract/DoubleIt}DoubleItService#DoubleIt". For example:
    A sample authorization request looks like:
    If you are interested in XACML 3.0 please get involved with the Apache OpenAz project! Once the project gets more mature, the PEP code in my project will probably make it over to Apache CXF so that users have the option of supporting XACML 2.0 or 3.0 (and XML or JSON) with their web services.
    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.1 and 1.1.3 released

    Colm O hEigeartaigh - Thu, 08/27/2015 - 18:50
    Apache CXF Fediz 1.2.1 and 1.1.3 have been released. Both releases contain updates to the underlying CXF dependency, as well as a number of minor bug-fixes and improvements. However the most important enhancement is a fix for a recent security advisory:
    • CVE-2015-5175: Apache CXF Fediz application plugins are vulnerable to Denial of Service (DoS) attacks
    Apache CXF Fediz is a subproject of Apache CXF which implements the WS-Federation Passive Requestor Profile for SSO specification. It provides a number of container based plugins to enable SSO for Relying Party applications. These plugins are potentially vulnerable to DoS attacks due to the fact that support for Document Type Declarations (DTDs) is not disabled when parsing the response from the Identity Provider (IdP).
    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.0 tutorial - part VII

    Colm O hEigeartaigh - Tue, 08/25/2015 - 17:36
    This is the seventh and final blog post on a series of new features introduced in Apache CXF Fediz 1.2.0. The previous post looked at the new REST API of the IdP. Up to now, we have only covered the basic scenario where the application and the IdP are in the same realm. However, a more sophisticated example is when the application is in a different realm. In this case, the IdP must redirect the user to the home IdP of the application for authentication. The IdP has supported this functionality up to now using WS-Federation only. However, the 1.2.0 IdP supports the ability to redirect to a SAML SSO IdP, thus acting as an identity broker between the two protocols. We will cover this functionality in this tutorial.

    1) Setup simpleWebapp + SAML SSO IdP

    As with previous tutorials, please follow the first tutorial to deploy the Fediz IdP + STS to Apache Tomcat, as well as the "simpleWebapp. However, this time the "simpleWebapp" is going to be deployed in a different realm. Edit 'conf/fediz_config.xml' and add the following under the "protocol" section:
    • <homeRealm type="String">urn:org:apache:cxf:fediz:idp:realm-B</homeRealm>
    This tells the IdP that the application is to be authenticated in "realm-B".

    The next thing we are going to do is to set up a SAML SSO IdP which will authenticate users who want to access "simpleWebapp". In this tutorial we will just use a mocked SAML SSO IdP in the Fediz system tests for convenience. Build the war as in the following steps + deploy to Tomcat:
    2) Configure the Fediz IdP

    Next we need to take a look at configuring the Fediz IdP so that it knows where to find the SAML SSO IdP associated with "realm B" and how to communicate with it. Edit 'webapps/fediz-idp/WEB-INF/classes/entities-realma.xml':

    In the 'idp-realmA' bean:
    • Change the port in "idpUrl" to "8443". 
    In the 'trusted-idp-realmB' bean:
    • Change the "url" value to "https://localhost:8443/samlssoidp/samlsso".
    • Change the "protocol" value to "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser".
    • Add the following: <property name="parameters"><util:map><entry key="support.deflate.encoding" value="true" /></util:map></property>
    The "parameters" map above is a way to provide SAML SSO specific configuration options to the Fediz IdP. The following options can be configured:
    • sign.request - Whether to sign the request or not. The default is "true".
    • require.keyinfo - Whether to require a KeyInfo or not when processing a (signed) Response. The default is "true".
    • require.signed.assertions - Whether the assertions contained in the Response must be signed or not. The default is "true".
    • require.known.issuer - Whether we have to "know" the issuer of the SAML Response or not. The default is "true".
    • support.base64.encoding - Whether we BASE-64 decode the response or not. The default is "true".
    • support.deflate.encoding - Whether we support Deflate encoding or not. The default is "false".
    Redeploy the Fediz IdP + navigate to the following URL in a browser:
    • https://localhost:8443/fedizhelloworld/secure/fedservlet
    You will see that the Fediz IdP will redirect the browser to the mocked SAML SSO IdP for authentication (authenticate with "ALICE/ECILA") and then back to the Fediz IdP and eventually back to the client application.


    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.0 tutorial - part VI

    Colm O hEigeartaigh - Wed, 08/19/2015 - 17:55
    This is the sixth in a series of posts on the new features of Apache CXF Fediz 1.2.0. The previous post looked at Single Sign Out support in Fediz. In this article we will briefly cover the new REST API of the Fediz IdP. Prior to the 1.2.0 release all of the IdP configuration was done in a static way using Spring. If the IdP administrator wished to change the claims for a particular application, then the change would necessitate restarting the IdP. In contrast, the Fediz 1.2.0 IdP persists the configuration to a database using JPA. In addition, it allows access to this configuration via a REST API powered by Apache CXF.

    To get started, please follow step 1 of the first tutorial to deploy the Fediz IdP to Apache Tomcat. The REST API is described by a WADL document available at the following URL:
    • https://localhost:8443/fediz-idp/services/rs?_wadl
    The WADL document describes the following resource URIs:
    • services/rs/idps - An IdP for a given realm. 
    • services/rs/claims - The claims that are available in the IdP.
    • services/rs/applications - The applications that are defined in the IdP.
    • services/rs/trusted-idps - The trusted IdPs that are defined in the IdP.
    • services/rs/roles - The roles associated with the REST API.
    By using the standard HTTP verbs in the usual way you can retrieve, store, modify and remove items from the IdP configuration. For example, to see (GET) the configuration associated with the IdP for "realm A" navigate to the following URL in a browser:
    • https://localhost:8443/fediz-idp/services/rs/idps/urn:org:apache:cxf:fediz:idp:realm-A
    The user credentials are defined in "webapps/fediz-idp/WEB-INF/classes/users.properties". You can use "admin/password" by default to access the API. Here you can see the protocols supported, the token types offered, the different ways of authenticating to the IdP, the claim types offered, the applications supported, etc. Note that by default the information returned in a GET request is in XML format. You can return it in JSON format just by appending ".json" to the URL:
    For much more information on how to use the new REST API, please see Oliver Wulff's blog on this topic.
    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.0 tutorial - part V

    Colm O hEigeartaigh - Fri, 08/07/2015 - 18:43
    This is the fifth in a series of posts on the new features available in Apache CXF Fediz 1.2.0. The previous article described a new container-independent Relying Party (RP) plugin available in Fediz 1.2.0 based on Apache CXF. In this post we will take a look at two new features, support for Single Sign Out and the ability to publish metadata for both RP plugins and the IdP.

    1) Single Sign Out support in Fediz

    An important new feature in Fediz 1.2.0 is the ability to perform Single Sign Out both at the RP and IdP. The user can log out at either the RP or IdP by adding "?wa=wsignout1.0" to the relevant URL. Alternatively, two new configuration options are added for the RP:
    • logoutURL - The logout URL to trigger federated logout
    • logoutRedirectTo - URL landing-page after successful logout.
    To see how this works in practice, follow the first tutorial to set up the hello world demo in Tomcat, and log on via:
    • https://localhost:8443/fedizhelloworld/secure/fedservlet
    After successful authentication, you will see a basic webpage detailing the User principal, roles, and the underlying SAML Assertion. Now what if you want to log out from the application? From Fediz 1.2.0 it's simple. Navigate to the following URL:
    • https://localhost:8443/fedizhelloworld/secure/fedservlet?wa=wsignout1.0
    The browser will be redirected to the logout page for the IdP:

    Click "Logout" and you see a page confirming that Logout was successful (in both the RP + IdP). To confirm this, navigate again to the application URL, and you will see that you are redirected back to the IdP for authentication. The user can also logout directly at the IdP by navigating to:
    • https://localhost:8443/fediz-idp/federation?wa=wsignout1.0
    2) Metadata Support in Fediz

    It has been possible since Fediz 1.0.0 to publish the Metadata document associated with a Relying Party using the Tomcat plugin. This Metadata document is built dynamically using the Fediz configuration values and is published at the standard URL. Here is a screenshot of a request using the "fedizhelloworld" demo:

    This document describes the endpoint address of the service, the realm of the service, and the claims (both required and optional). The metadata document can also be signed by specifying a "signingKey" in the Fediz configuration.

    So what's new in Fediz 1.2.0? The first thing is that it was only possible previously to publish the metadata document when using the Tomcat plugin. In Fediz 1.2.0, this has been extended to cover the other plugins, i.e. Jetty, Spring, etc. In addition, the forthcoming Fediz 1.2.1 release adds support for Metadata to the IdP. The Metadata is available at the same standard URL as for the RP, e.g.:

    This signed document describes the URL of the STS, as well as that of the IdP itself, and the claims that are offered by the IdP.
    Categories: Colm O hEigeartaigh

    (Slightly) Faster WS-Security using MTOM in Apache CXF 3.1.2

    Colm O hEigeartaigh - Fri, 07/17/2015 - 17:31
    A recent issue was reported at Apache CXF to do with the inability to process certain WS-Security requests that were generated by Metro or .NET when MTOM was enabled. In this case, Metro and .NET avoid BASE-64 encoding bytes and inserting them directly into the message (e.g. for BinarySecurityTokens or the CipherValue data associated with EncryptedData or EncryptedKey Elements). Instead the raw bytes are stored in a message attachment, and referred to in the message via xop:Include. Support for processing these types of requests has been added for WSS4J 2.0.5 and 2.1.2.

    In addition, CXF 3.1.2 now has the ability to avoid the BASE-64 encoding step when creating requests when MTOM is enabled, something that we will look at in this post. The advantage of this is that is marginally more efficient due to avoiding BASE-64 encoding at the sending side, and BASE-64 decoding on the receiving side.

    1) Storing message bytes in attachments in WSS4J

    A new WSS4J configuration property has been added in WSS4J 2.0.5/2.1.2 to support storing message bytes in attachments. This property is used when configuring WS-Security via the "action" based approach in CXF:
    • storeBytesInAttachment: Whether to store bytes (CipherData or BinarySecurityToken) in an attachment. The default is false, meaning that bytes are BASE-64 encoded and "inlined" in the message.
    WSS4J is stack-neutral, meaning that it has no concept of what a message attachment actually is. So for this to work, a CallbackHandler must be set on the RequestData Object, that knows how to retrieve attachments, as well as write modified/new attachments out. If you are using Apache CXF then this is taken care for you automatically.

    There is another configuration property that is of interest on the receiving side:
    • expandXOPIncludeForSignature: Whether to expand xop:Include Elements encountered when verifying a Signature. The default is true, meaning that the relevant attachment bytes are BASE-64 encoded and inserted into the Element. This ensures that the actual bytes are signed, and not just the reference.
    So for example, if an encrypted SOAP Body is signed, the default behaviour is to expand the xop:Include Element to make sure that we are verifying the signature on the SOAP Body. On the sending side, we must have a signature action *before* an encryption action, for this same reason. If we encrypt before signing, then WSS4J will turn off the "storeBytesInAttachment" property, to make sure that we are not signing a reference.

    2) Storing message bytes in attachments with WS-SecurityPolicy

    A new security configuration property is also available in Apache CXF to control the ability to store message bytes in attachments with WS-Security when WS-SecurityPolicy is used:
    • ws-security.store.bytes.in.attachment: Whether to store bytes (CipherData or BinarySecurityToken) in an attachment. The default is true if MTOM is enabled.
    This property is also available in CXF 3.0.6, but is it is "false" by default. Similar to the action case, CXF will turn off this property by default in either of the following policy cases:
    • If sp:EncryptBeforeSigning is present
    • If sp:ProtectTokens is present. In this case, the signing cert is itself signed, and again we want to avoid signing a reference rather than the certificate bytes.
    3) Tests

    To see this new functionality in action, take a look at the MTOMSecurityTest in CXF's ws-security systests module. It has three methods that test storing bytes in attachments with a symmetric binding, asymmetric binding + an "action based" approach to configuring WS-Security. Enable logging to see the requests and responses. The encrypted SOAP Body now contains a CipherValue that does not include the BASE-64 encoded bytes any more:

    The referenced attachment looks like:


    Finally, I wrote a blog post some time back about using Apache JMeter to load-test security-enabled CXF-based web services. I decided to modify the standard symmetric and asymmetric tests, so that the CXF service was MTOM enabled, so that the ability to store message bytes in the attachments was switched on with CXF 3.1.2. The results for both test-cases showed that throughput was around 1% higher when message bytes were stored in attachments. Bear in mind that the change just measures the service creation change, the client request was still non-MTOM aware as it is just pasted into JMeter. So one would expect up to a 4% improvement for a fully MTOM-aware client + service invocation:


    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.0 tutorial - part IV

    Colm O hEigeartaigh - Thu, 07/16/2015 - 17:40
    This is the fourth in a series of blog posts on the new features and changes in Apache CXF Fediz 1.2.0. The last two articles focused on how clients can authenticate to the IdP in Fediz 1.2.0 using Kerberos and TLS client authentication. In this post we will divert our attention from the IdP for the time being, and look at a new container-independent Relying Party (RP) plugin available in Fediz 1.2.0 based on Apache CXF.

    1) RP plugins in Fediz

    Apache Fediz ships with a number of RP plugins to secure your web application. These plugins are container-dependent, meaning that if your web app is deployed in say Apache Tomcat, you need to use the Tomcat plugin in Fediz. The following plugins were available prior to Fediz 1.2.0:
    The CXF plugin referred to here was not a full WS-Federation RP plugin as in the other modules. Instead, it consisted of a mechanism that allows the SSO (SAML) token retrieved as part of the WS-Federation process to be used by CXF client code, if the web application needed to obtain another token "on behalf of" the other token when making some subsequent web services call.

    2) CXF RP plugin in Fediz 1.2.0

    In Fediz 1.2.0, the CXF plugin mentioned above now contains a fully fledged WS-Federation RP implementation that can be used to secure a JAX-RS service, rather than using one of the container dependent plugins. Lets see how this works using a test-case:
    • 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.
    The test-case consists of two modules. The first is a web application which contains a simple JAX-RS service, which has a single GET method to return a doubled number. The method is secured with a @RolesAllowed annotation, meaning that only a user in roles "User", "Admin", or "Manager" can access the service.

    This is enforced via CXF's SecureAnnotationsInterceptor. Finally WS-Federation is enabled for the service via the JAX-RS Provider called the FedizRedirectBindingFilter, available in the CXF plugin in Fediz. This takes a "configFile" parameter, which is a link to the standard Fediz plugin configuration file:


    It's as easy as this to secure your CXF JAX-RS service using WS-Federation! The remaining module in the test above deploys the IdP + STS from Fediz in Apache Tomcat. It then takes the "double-it" war above and also deployed it in Tomcat.

    Finally, it uses Htmlunit to make an invocation on the service, and checks that access is granted to the service. Alternatively, you can comment the @Ignore annotation of the "testInBrowser" method, and copy the printed out URL into a browser to test the service directly (user credentials: "alice/ecila").
    Categories: Colm O hEigeartaigh

    Apache CXF Fediz 1.2.0 tutorial - part III

    Colm O hEigeartaigh - Wed, 07/15/2015 - 17:22
    This is the third in a series of blog posts on the new features and changes in Apache CXF Fediz 1.2.0. The previous blog entry described how different client authentication mechanisms are supported in the IdP, and how to configure client authentication via an X.509 certificate, a new feature in Fediz 1.2.0. Another new authentication mechanism in Fediz 1.2.0 is the ability to authenticate to the IdP using Kerberos, which we will cover in this article.

    1) Kerberos client authentication in the IdP

    Recall that the Apache Fediz IdP in 1.2.0 supports different client authentication methods by default using different URL paths. In particular for Kerberos, the URL path is:
    • /federation/krb -> authentication using Kerberos
    The default value for the "wauth" parameter added by the service provider to the request to activate this URL path is:
    • http://docs.oasis-open.org/wsfed/authorization/200706/authntypes/SslAndKey
    When the IdP receives a request at the URL path configured for Kerberos, it sends back a request for a Negotiate Authorization header if none is present. Otherwise it parses the header and BASE-64 decodes the Kerberos token and dispatches it to the configured authentication provider. Kerberos tokens are authenticated in the IdP via the STSKrbAuthenticationProvider, which is configured in the Spring security-config.xml

    2) Authenticating Kerberos tokens in the IdP

    The IdP supports two different ways of validating Kerberos tokens:
    • Passthrough Authentication. Here we do not authenticate the Kerberos token at all in the IdP, but pass it through to the STS for authentication. This is similar to what is done for the Username/Password authentication case. The default security binding of the STS for this scenario requires a KerberosToken Supporting Token. This is the default way of authenticating Kerberos tokens in the IdP.
    • Delegation. If delegation is enabled in the IdP, then the received token is validated locally in the IdP. The delegated credential is then used to get a new Kerberos Token to authenticate the STS call "on behalf of" the original user. 
    To enable the delegation scenario, simply update the STSKrbAuthenticationProvider bean in the security-config.xml,
    set the "requireDelegation" property to "true", and configure the kerberosTokenValidator property to validate the received Kerberos token:

    Categories: Colm O hEigeartaigh

    Securing Apache CXF with Apache Camel

    Colm O hEigeartaigh - Fri, 07/10/2015 - 18:45
    The previous post I wrote about how to integrate Apache CXF with Apache Camel. The basic test scenario involved using an Apache CXF proxy service to authenticate clients, and Apache Camel to route the authenticated requests to a backend service, which had different security requirements to the proxy. In this post, we will look at a slightly different scenario, where the duty of authenticating the clients shifts from the proxy service to Apache Camel itself. In addition, we will look at how to authorize the clients via different Apache Camel components.

    For a full description of the test scenario see the previous post. The Apache CXF based proxy service receives a WS-Security UsernameToken, which is used to authenticate the client. In the previous scenario, this was done at the proxy by supplying a CallbackHandler instance to verify the given username and password. However, this time we will just configure the proxy to pass the received credentials through to the route instead of authenticating them. This can be done by setting the JAX-WS property "ws-security.validate.token" to "false":

    So now it is up to the Camel route to authenticate and authorize the user credentials. Here are two possibilities using Apache Shiro and Spring Security.

    1) Apache Shiro

    I've covered previously how to use Apache Shiro to authenticate and authorize web service invocations using Apache CXF. Apache Camel ships with a camel-shiro component which allows you to authenticate and authorize Camel routes. The test-case can be downloaded and run here:
    • camel-cxf-proxy-shiro-demo: Some authentication and authorization tests for an Apache CXF proxy service using the Apache Camel Shiro component.
    Username, passwords and roles are stored in a file and parsed in a ShiroSecurityPolicy object:

    The Camel route is as follows:


    Note that the shiroHeaderProcessor bean processes the result from the proxy before applying the Shiro policy. This processor retrieves the client credentials (which are stored as a JAAS Subject in a header on the exchange) and extracts the username and password, storing them in special headers that are used by the Shiro component in Camel to get the username and password for authentication. 

    The authorization use-case uses the same route, however the ShiroSecurityPolicy bean enforces that the user must have a role of "boss" to invoke on the backend service:


    2) Spring Security 

    I've also covered previously how to use Spring Security to authenticate and authorize web service invocations using Apache CXF. Apache Camel ships with a camel-spring-security component which allows you to authenticate and authorize Camel routes. The test-case can be downloaded and run here:
    Like the Shiro test-case, username, passwords and roles are stored in a file, which is used to create an authorizationPolicy bean:
    The Camel route is exactly the same as in the Shiro example above, except that a different processor implementation is used. The SpringSecurityHeaderProcessor bean used in the tests translates the user credentials into a Spring Security UsernamePasswordAuthenticationToken principal, which is added to the JAAS Subject stored under the Exchange.AUTHENTICATION header. This principal is then used by the Spring Security component to authenticate the request.

    To authorize the request, a different authorizationPolicy configuration is required:


    Categories: Colm O hEigeartaigh

    Pages

    Subscribe to Talend Community Coders aggregator - Colm O hEigeartaigh