67
Peter Arockiaraj Can you hear me now?…Good! Home About Me Developing CXF WS-Security with SAML 4 Votes Introduction In this article we are going to develop a web service by using Spring and CXF with WS-Security (SAML). This article provides steps (step by step) to create & deploy web services by usingSpring and CXF with WS-Security (SAML). Please go through below to find sample web services. Software Requirements EClipse (Java IDE)- Optional 1. CXF Jars (Required for Compilation-Download from http://cxf.apache.org/download.html ) 2. The Code In this example, we are going to create a Hello service. In this example, we are going to use a code-first approach for this service using JAX-WS annotations. Creating Server and Client Certificates For the Signature and Encryption actions, you’ll need to create a public & private key for the entities involved. You can generate a key pair for the development environment via the following steps. Keep in mind these will not be signed by an external authority like Verisign Keytool is inbuild tool which is comes with jdk. Follow the steps to create client and server certificates (Refer following site) http://pa55word.wordpress.com/ 1. When urgently you need some keystores and truststores to test out some security related java code this is a useful bat file to have. Copy the code below and create a bat file. run it and you got your stuff. keytool -genkey -alias serverkeys -keyalg RSA -keystore server.keystore -storepass changeit -keypass changeit -dname “CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, ST=MYSTATE, C=MY” keytool -export -alias serverkeys -keystore server.keystore -storepass changeit -file server.cer Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu... 1 of 67 6/22/2011 2:07 PM

(Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Embed Size (px)

Citation preview

Page 1: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Peter Arockiaraj

Can you hear me now?…Good!

HomeAbout Me

Developing CXF WS-Security with SAML

4 Votes

Introduction

In this article we are going to develop a web service by using Spring and CXF with WS-Security (SAML).

This article provides steps (step by step) to create & deploy web services by usingSpring and CXF with

WS-Security (SAML). Please go through below to find sample web services.

Software Requirements

EClipse (Java IDE)- Optional1.

CXF Jars (Required for Compilation-Download from http://cxf.apache.org/download.html)2.

The Code

In this example, we are going to create a Hello service. In this example, we are going to use a code-first

approach for this service using JAX-WS annotations.

Creating Server and Client Certificates

For the Signature and Encryption actions, you’ll need to create a public & private key for the entities

involved. You can generate a key pair for the development environment via the following steps. Keep in mind

these will not be signed by an external authority like Verisign

Keytool is inbuild tool which is comes with jdk.

Follow the steps to create client and server certificates (Refer following site)

http://pa55word.wordpress.com/1.

When urgently you need some keystores and truststores to test out some security related java code this is a

useful bat file to have. Copy the code below and create a bat file. run it and you got your stuff.

keytool -genkey -alias serverkeys -keyalg RSA -keystore server.keystore -storepass changeit -keypass

changeit -dname “CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, ST=MYSTATE, C=MY”

keytool -export -alias serverkeys -keystore server.keystore -storepass changeit -file server.cer

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

1 of 67 6/22/2011 2:07 PM

Page 2: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

keytool -genkey -alias clientkeys -keyalg RSA -keystore client.keystore -storepass changeit -keypass

changeit -dname “CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, S=MY

STATE, C=MY”

keytool -export -alias clientkeys -keystore client.keystore -storepass changeit -file client.cer

keytool -import -v -keystore client.truststore -storepass changeit -file server.cer

keytool -import -v -keystore server.truststore -storepass changeit -file client.cer

It generates a keystore called server.keystore with password changeit. Then it

creates server certificate server.cer.

Then it generates a keystore called client.keystore with password changeit. Creates a client certificate namedclient.cer

Next it imports server certificate into client truststore and client certificate into server truststore.

These are self signed certificates. Good for internal use. You can use open ssland create certificates. But this bat file is short and sweet for immediate use.

When you paste it you do have to be careful about keywords not getting split up like wordpress does.

Creating Server Application

Step 1: Download Following Jar files.

activation.jar

aopalliance-1.0.jar

commons-collections-3.2.jar

commons-lang-2.1.jar

commons-logging-1.1.jar

geronimo-activation-2.0.1.jar

geronimo-annotation_1.0_spec-1.1.jar

geronimo-javamail_1.4_mail-1.2.jar

geronimo-servlet_2.5_spec-1.1.jar

geronimo-ws-metadata_2.0_spec-1.1.1.jar

jaxb-api.jar

jaxb-api-2.0.jar

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

2 of 67 6/22/2011 2:07 PM

Page 3: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

jaxb-impl-2.0.5.jar

jaxb-xjc.jar

jaxws-api.jar

mail.jar

neethi-2.0.jar

opensaml-1.0.1.jar

saaj-api.jar

saaj-impl.jar

spring-beans-2.0.6.jar

spring-context-2.0.6.jar

spring-core-2.0.6.jar

spring-web-2.0.6.jar

stax-api-1.0.1.jar

velocity-1.5.jar

wsdl4j-1.6.1.jar

wstx-asl-3.2.1.jar

xalan-2[1].6.0.jar

xalan-2[1].7.0.jar

xml-resolver-1.2.jar

cxf-bundle-2.0.4-incubator.jar

XmlSchema-1.3.2.jar

wss4j-1.5.1.jar

keyexport.jar

pkcs12import.jar

security-plugin.jar

wss-provider-update.jar

xws-security_jaxrpc.jar

xws-security.jar

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

3 of 67 6/22/2011 2:07 PM

Page 4: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

xmlsec-1.3.0.jar

Step 2: Create New Java project in eclipse (CXFSAMLSecurity).

Step 3: Create WEB-INF folder inside project folder.

Step 4: Create classes folder inside WEB-INF folder.

Step 5: Create lib folder inside WEB-INF folder.

Step 6: Copy all the jar file into lib folder.

Step 7: Add all jar files into classpath (In Eclipse set java build path->Libraries). Add set Default outputfolder into CXFSAMLSecurity/WEB-INF/classes

Step 8: Create Remote Interface IHello.java

package com.sungard.cxf.example.server;

import javax.jws.WebService;

@WebService

public interface IHello {

public String sayHello(String value);

}

Step 9: Create Implementation Class IHello_Impl.java

package com.sungard.cxf.example.server;

import javax.jws.WebService;

@WebService(endpointInterface = “com.sungard.cxf.example.server.IHello”)

public class IHello_Impl implements IHello {

public String sayHello(String value) {

return “You Said” + value;

}

}

Step 10: Create ServerSecurityEnvironmentHandler.java file to handle usernames and passwords. Here youhave to give server certificate, server trust certificate alias name for checking. Password is alias password.

Also you have to give client keystore file passwords also.

private String keyStorePassword = “changeit”;

private String trustStorePassword = “changeit”;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

4 of 67 6/22/2011 2:07 PM

Page 5: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

else if (callbacks[i] instanceof WSPasswordCallback) {

System.out.println(“handle::WSPasswordCallback”);

WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];

cb.setPassword(“changeit”);

}

package com.sungard.cxf.example.server;

import java.io.IOException;

import java.math.BigInteger;

import java.net.URL;

import java.security.KeyStore;

import java.security.PrivateKey;

import java.security.cert.CertPathBuilder;

import java.security.cert.Certificate;

import java.security.cert.CertificateExpiredException;

import java.security.cert.CertificateNotYetValidException;

import java.security.cert.PKIXBuilderParameters;

import java.security.cert.PKIXCertPathBuilderResult;

import java.security.cert.X509CertSelector;

import java.security.cert.X509Certificate;

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.Calendar;

import java.util.Date;

import java.util.Enumeration;

import java.util.GregorianCalendar;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.UnsupportedCallbackException;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

5 of 67 6/22/2011 2:07 PM

Page 6: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

import org.apache.ws.security.WSPasswordCallback;

//import com.sun.org.apache.xml.internal.security.utils.RFC2253Parser;

import com.sun.xml.wss.impl.callback.CertificateValidationCallback;

import com.sun.xml.wss.impl.callback.DecryptionKeyCallback;

import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;

import com.sun.xml.wss.impl.callback.PasswordValidationCallback;

import com.sun.xml.wss.impl.callback.SignatureKeyCallback;

import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;

import com.sun.xml.wss.impl.callback.TimestampValidationCallback;

import com.sun.xml.wss.impl.misc.SecurityUtil;

/**

* A sample implementation of a CallbackHandler.

*/

public class ServerSecurityEnvironmentHandler implements CallbackHandler {

private KeyStore keyStore;

private KeyStore trustStore;

private String keyStorePassword = “changeit”;

private String trustStorePassword = “changeit”;

private static final UnsupportedCallbackException unsupported = new UnsupportedCallbackException(

null, “Unsupported Callback Type Encountered”);

public ServerSecurityEnvironmentHandler() throws Exception {

initTrustStore();

initKeyStore();

}

public void handle(Callback[] callbacks) throws IOException,

UnsupportedCallbackException {

System.out.println(“Entered::ServerSecurityEnvironmentHandler::handle”);

for (int i = 0; i < callbacks.length; i++) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

6 of 67 6/22/2011 2:07 PM

Page 7: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

System.out.println(“handle::For-1″);

if (callbacks[i] instanceof PasswordValidationCallback) {

System.out.println(“handle::PasswordValidationCallback”);

PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];

if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {

System.out.println(“handle::PlainTextPasswordRequest”);

cb.setValidator(new PlainTextPasswordValidator());

} else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {

System.out.println(“handle::DigestPasswordRequest”);

PasswordValidationCallback.DigestPasswordRequest request =(PasswordValidationCallback.DigestPasswordRequest) cb

.getRequest();

String username = request.getUsername();

if (“Ron”.equals(username)) {

request.setPassword(“noR”);

cb

.setValidator(new PasswordValidationCallback.DigestPasswordValidator());

}

} else {

throw unsupported;

}

} else if (callbacks[i] instanceof TimestampValidationCallback) {

System.out.println(“handle::TimestampValidationCallback”);

TimestampValidationCallback cb = (TimestampValidationCallback) callbacks[i];

cb.setValidator(new DefaultTimestampValidator());

} else if (callbacks[i] instanceof SignatureVerificationKeyCallback) {

System.out.println(“handle::SignatureVerificationKeyCallback”);

SignatureVerificationKeyCallback cb = (SignatureVerificationKeyCallback) callbacks[i];

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

7 of 67 6/22/2011 2:07 PM

Page 8: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) {

System.out.println(“handle::X509SubjectKeyIdentifierBasedRequest”);

// subject keyid request

SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request =(SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb

.getRequest();

X509Certificate cert = getCertificateFromTrustStore(request

.getSubjectKeyIdentifier());

request.setX509Certificate(cert);

} else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) {

// issuer serial request

System.out.println(“handle::X509IssuerSerialBasedRequest”);

SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request =(SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) cb

.getRequest();

X509Certificate cert = getCertificateFromTrustStore(request

.getIssuerName(), request.getSerialNumber());

request.setX509Certificate(cert);

} else {

throw unsupported;

}

} else if (callbacks[i] instanceof SignatureKeyCallback) {

System.out.println(“handle::SignatureKeyCallback”);

SignatureKeyCallback cb = (SignatureKeyCallback) callbacks[i];

if (cb.getRequest() instanceof SignatureKeyCallback.DefaultPrivKeyCertRequest) {

System.out.println(“handle::DefaultPrivKeyCertRequest”);

// default priv key cert req

SignatureKeyCallback.DefaultPrivKeyCertRequest request =(SignatureKeyCallback.DefaultPrivKeyCertRequest) cb

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

8 of 67 6/22/2011 2:07 PM

Page 9: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.getRequest();

getDefaultPrivKeyCert(request);

} else if (cb.getRequest() instanceof SignatureKeyCallback.AliasPrivKeyCertRequest) {

System.out.println(“handle::AliasPrivKeyCertRequest”);

SignatureKeyCallback.AliasPrivKeyCertRequest request =

(SignatureKeyCallback.AliasPrivKeyCertRequest) cb

.getRequest();

String alias = request.getAlias();

try {

X509Certificate cert = (X509Certificate) keyStore

.getCertificate(alias);

request.setX509Certificate(cert);

// Assuming key passwords same as the keystore password

PrivateKey privKey = (PrivateKey) keyStore.getKey(

alias, keyStorePassword.toCharArray());

request.setPrivateKey(privKey);

} catch (Exception e) {

System.out.println(“handle::AliasPrivKeyCertRequest::Exception”);

throw new IOException(e.getMessage());

}

} else {

System.out.println(“handle::AliasPrivKeyCertRequest::Exception::own::1″);

throw unsupported;

}

} else if (callbacks[i] instanceof DecryptionKeyCallback) {

DecryptionKeyCallback cb = (DecryptionKeyCallback) callbacks[i];

System.out.println(“handle::DecryptionKeyCallback”);

if (cb.getRequest() instanceof DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

9 of 67 6/22/2011 2:07 PM

Page 10: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

System.out.println(“handle::X509SubjectKeyIdentifierBasedRequest”);

DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request =

(DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb

.getRequest();

byte[] ski = request.getSubjectKeyIdentifier();

PrivateKey privKey = getPrivateKey(ski);

request.setPrivateKey(privKey);

} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBasedRequest) {

System.out.println(“handle::X509IssuerSerialBasedRequest”);

DecryptionKeyCallback.X509IssuerSerialBasedRequest request =(DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb

.getRequest();

String issuerName = request.getIssuerName();

BigInteger serialNumber = request.getSerialNumber();

PrivateKey privKey = getPrivateKey(issuerName, serialNumber);

request.setPrivateKey(privKey);

} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBasedRequest) {

System.out.println(“handle::X509CertificateBasedRequest”);

DecryptionKeyCallback.X509CertificateBasedRequest request =(DecryptionKeyCallback.X509CertificateBasedRequest) cb

.getRequest();

X509Certificate cert = request.getX509Certificate();

PrivateKey privKey = getPrivateKey(cert);

request.setPrivateKey(privKey);

} else {

System.out.println(“handle::X509CertificateBasedRequest::Exception::own:2″);

throw unsupported;

}

} else if (callbacks[i] instanceof EncryptionKeyCallback) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

10 of 67 6/22/2011 2:07 PM

Page 11: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

EncryptionKeyCallback cb = (EncryptionKeyCallback) callbacks[i];

System.out.println(“handle::EncryptionKeyCallback”);

if (cb.getRequest() instanceof EncryptionKeyCallback.AliasX509CertificateRequest) {

System.out.println(“handle::AliasX509CertificateRequest”);

EncryptionKeyCallback.AliasX509CertificateRequest request =

(EncryptionKeyCallback.AliasX509CertificateRequest) cb

.getRequest();

String alias = request.getAlias();

if (alias == null) {

System.out.println(“handle::AliasX509CertificateRequest::read”);

// plugin code here to read the cert from the

// ThreadLocal

} else {

try {

System.out.println(“handle::AliasX509CertificateRequest:try”);

X509Certificate cert = (X509Certificate) trustStore

.getCertificate(alias);

request.setX509Certificate(cert);

} catch (Exception e) {

System.out.println(“handle::AliasX509CertificateRequest::Exception”);

throw new IOException(e.getMessage());

}

}

} else {

System.out.println(“handle::AliasX509CertificateRequest::Exception::own::3″);

throw unsupported;

}

} else if (callbacks[i] instanceof CertificateValidationCallback) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

11 of 67 6/22/2011 2:07 PM

Page 12: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

System.out.println(“handle::CertificateValidationCallback”);

CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];

cb.setValidator(new X509CertificateValidatorImpl());

} else if (callbacks[i] instanceof CertificateValidationCallback) {

System.out.println(“handle::CertificateValidationCallback”);

CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];

cb.setValidator(new X509CertificateValidatorImpl());

} else if (callbacks[i] instanceof WSPasswordCallback) {

System.out.println(“handle::WSPasswordCallback”);

WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];

System.out.println(“handle::cb.getPassword()”+cb.getPassword());

cb.setPassword(“changeit”);

} else {

System.out.println(“handle::CallBack Class Name::”+callbacks[i].getClass().getName());

System.out.println(“handle::CertificateValidationCallback::Exception::own::4″);

throw unsupported;

}

}

System.out.println(“Leaving::ServerSecurityEnvironmentHandler::handle”);

}

private void initTrustStore() throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::initTrustStore”);

try {

URL truststoreURL = SecurityUtil

.loadFromClasspath(“server-truststore.jks”);

trustStore = KeyStore.getInstance(“JKS”);

trustStore.load(truststoreURL.openStream(), trustStorePassword

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

12 of 67 6/22/2011 2:07 PM

Page 13: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.toCharArray());

} catch (Exception e) {

e.printStackTrace();

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::initTrustStore”);

}

private void initKeyStore() throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::initKeyStore”);

try {

URL keystoreURL = SecurityUtil

.loadFromClasspath(“server-keystore.jks”);

keyStore = KeyStore.getInstance(“JKS”);

keyStore.load(keystoreURL.openStream(), keyStorePassword

.toCharArray());

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::initKeyStore”);

}

private X509Certificate getCertificateFromTrustStore(byte[] ski)

throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore”);

try {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

13 of 67 6/22/2011 2:07 PM

Page 14: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Enumeration aliases = trustStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

Certificate cert = trustStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

byte[] keyId = getSubjectKeyIdentifier(x509Cert);

if (keyId == null) {

// Cert does not contain a key identifier

continue;

}

if (Arrays.equals(ski, keyId)) {

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::1″);

return x509Cert;

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::2″);

return null;

}

private X509Certificate getCertificateFromTrustStore(String issuerName,

BigInteger serialNumber) throws IOException {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

14 of 67 6/22/2011 2:07 PM

Page 15: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple”);

try {

Enumeration aliases = trustStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

Certificate cert = trustStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser.normalize(x509Cert

.getIssuerDN().getName());

BigInteger thisSerialNumber = x509Cert.getSerialNumber();

if (thisIssuerName.equals(issuerName)

&& thisSerialNumber.equals(serialNumber)) {

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple::1″);

return x509Cert;

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple::2″);

return null;

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

15 of 67 6/22/2011 2:07 PM

Page 16: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

public PrivateKey getPrivateKey(byte[] ski) throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey”);

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

byte[] keyId = getSubjectKeyIdentifier(x509Cert);

if (keyId == null) {

// Cert does not contain a key identifier

continue;

}

if (Arrays.equals(ski, keyId)) {

// Asuumed key password same as the keystore password

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::2″);

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

}

}

} catch (Exception e) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

16 of 67 6/22/2011 2:07 PM

Page 17: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::2″);

return null;

}

public PrivateKey getPrivateKey(String issuerName, BigInteger serialNumber)

throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey::multiple”);

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser.normalize(x509Cert

.getIssuerDN().getName());

BigInteger thisSerialNumber = x509Cert.getSerialNumber();

if (thisIssuerName.equals(issuerName)

&& thisSerialNumber.equals(serialNumber)) {

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::multiple::1″);

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

17 of 67 6/22/2011 2:07 PM

Page 18: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::multiple::1″);

return null;

}

public PrivateKey getPrivateKey(X509Certificate certificate)

throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey::certificate”);

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert != null && cert.equals(certificate))

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::certificate::1″);

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

18 of 67 6/22/2011 2:07 PM

Page 19: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::certificate::2″);

return null;

}

private void getDefaultPrivKeyCert(

SignatureKeyCallback.DefaultPrivKeyCertRequest request)

throws IOException {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getDefaultPrivKeyCert”);

String uniqueAlias = null;

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String currentAlias = (String) aliases.nextElement();

if (keyStore.isKeyEntry(currentAlias)) {

Certificate thisCertificate = keyStore

.getCertificate(currentAlias);

if (thisCertificate != null) {

if (thisCertificate instanceof X509Certificate) {

if (uniqueAlias == null) {

uniqueAlias = currentAlias;

} else {

// Not unique!

uniqueAlias = null;

break;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

19 of 67 6/22/2011 2:07 PM

Page 20: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

}

}

}

}

if (uniqueAlias != null) {

request.setX509Certificate((X509Certificate) keyStore

.getCertificate(uniqueAlias));

request.setPrivateKey((PrivateKey) keyStore.getKey(uniqueAlias,

keyStorePassword.toCharArray()));

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getDefaultPrivKeyCert”);

}

private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {

System.out

.println(“Entered::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier”);

String SUBJECT_KEY_IDENTIFIER_OID = “2.5.29.14″;

byte[] subjectKeyIdentifier = cert

.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);

if (subjectKeyIdentifier == null)

return null;

try {

sun.security.x509.KeyIdentifier keyId = null;

sun.security.util.DerValue derVal = new sun.security.util.DerValue(

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

20 of 67 6/22/2011 2:07 PM

Page 21: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

new sun.security.util.DerInputStream(subjectKeyIdentifier)

.getOctetString());

keyId = new sun.security.x509.KeyIdentifier(derVal.getOctetString());

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::1″);

return keyId.getIdentifier();

} catch (NoClassDefFoundError ncde) {

if (subjectKeyIdentifier == null)

return null;

byte[] dest = new byte[subjectKeyIdentifier.length - 4];

System.arraycopy(subjectKeyIdentifier, 4, dest, 0,

subjectKeyIdentifier.length – 4);

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::2″);

return dest;

} catch (java.io.IOException ex) {

// ignore

System.out

.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::3″);

return null;

}

}

private class PlainTextPasswordValidator implements

PasswordValidationCallback.PasswordValidator {

public boolean validate(PasswordValidationCallback.Request request)

throws PasswordValidationCallback.PasswordValidationException {

System.out.println(“Entered::PlainTextPasswordValidator::validate”);

PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest =

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

21 of 67 6/22/2011 2:07 PM

Page 22: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

(PasswordValidationCallback.PlainTextPasswordRequest) request;

if (“Ron”.equals(plainTextRequest.getUsername())

&& “noR”.equals(plainTextRequest.getPassword())) {

System.out

.println(“Leaving::PlainTextPasswordValidator::validate::true”);

return true;

}

System.out

.println(“Leaving::PlainTextPasswordValidator::validate::false”);

return false;

}

}

private class DefaultTimestampValidator implements

TimestampValidationCallback.TimestampValidator {

public void validate(TimestampValidationCallback.Request request)

throws TimestampValidationCallback.TimestampValidationException {

System.out.println(“Entered::DefaultTimestampValidator::validate”);

// validate timestamp creation and expiration time.

TimestampValidationCallback.UTCTimestampRequest utcTimestampRequest =(TimestampValidationCallback.UTCTimestampRequest) request;

SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(

“yyyy-MM-dd’T'HH:mm:ss’Z'”);

SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(

“yyyy-MM-dd’T'HH:mm:ss’.'SSS’Z'”);

Date created = null;

Date expired = null;

try {

try {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

22 of 67 6/22/2011 2:07 PM

Page 23: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

created = calendarFormatter1.parse(utcTimestampRequest

.getCreated());

if (utcTimestampRequest.getExpired() != null)

expired = calendarFormatter1.parse(utcTimestampRequest

.getExpired());

} catch (java.text.ParseException pe) {

created = calendarFormatter2.parse(utcTimestampRequest

.getCreated());

if (utcTimestampRequest.getExpired() != null)

expired = calendarFormatter2.parse(utcTimestampRequest

.getExpired());

}

} catch (java.text.ParseException pe) {

throw new TimestampValidationCallback.TimestampValidationException(

pe.getMessage());

}

long maxClockSkew = utcTimestampRequest.getMaxClockSkew();

long timestampFreshnessLimit = utcTimestampRequest

.getTimestampFreshnessLimit();

// validate creation time

validateCreationTime(created, maxClockSkew, timestampFreshnessLimit);

// validate expiration time

if (expired != null)

validateExpirationTime(expired, maxClockSkew,

timestampFreshnessLimit);

System.out.println(“Leaving::DefaultTimestampValidator::validate”);

}

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

23 of 67 6/22/2011 2:07 PM

Page 24: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

public void validateExpirationTime(Date expires, long maxClockSkew,

long timestampFreshnessLimit)

throws TimestampValidationCallback.TimestampValidationException {

System.out

.println(“Enterd::DefaultTimestampValidator::validateExpirationTime”);

Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),

maxClockSkew, false);

if (expires.before(currentTime)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The current time is ahead of the expiration time in Timestamp”);

}

System.out

.println(“Leaving::DefaultTimestampValidator::validateExpirationTime”);

}

public void validateCreationTime(Date created, long maxClockSkew,

long timestampFreshnessLimit)

throws TimestampValidationCallback.TimestampValidationException {

System.out

.println(“Enterd::DefaultTimestampValidator::validateCreationTime”);

Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,

timestampFreshnessLimit);

System.out.println(“Validate Creation time called current=” + current);

System.out.println(“Validate Creation time called created=” + created);

if (created.before(current)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The creation time is older than “

+ ” currenttime – timestamp-freshness-limit – max-clock-skew”);

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

24 of 67 6/22/2011 2:07 PM

Page 25: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),

maxClockSkew, true);

System.out.println(“Validate Creation time called currentTime=”

+ currentTime);

System.out.println(“Validate Creation time called created=” + created);

if (currentTime.before(created)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The creation time is ahead of the current time.”);

}

System.out

.println(“Leaving::DefaultTimestampValidator::validateCreationTime”);

}

private static Date getFreshnessAndSkewAdjustedDate(long maxClockSkew,

long timestampFreshnessLimit) {

System.out

.println(“Enterd::DefaultTimestampValidator::getFreshnessAndSkewAdjustedDate”);

Calendar c = new GregorianCalendar();

long offset = c.get(Calendar.ZONE_OFFSET);

if (c.getTimeZone().inDaylightTime(c.getTime())) {

offset += c.getTimeZone().getDSTSavings();

}

long beforeTime = c.getTimeInMillis();

long currentTime = beforeTime – offset;

System.out.println(“MaxSkew=” + maxClockSkew + ” freshness=”

+ timestampFreshnessLimit);

long adjustedTime = currentTime – maxClockSkew

- timestampFreshnessLimit;

c.setTimeInMillis(adjustedTime);

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

25 of 67 6/22/2011 2:07 PM

Page 26: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

System.out

.println(“Leaving::DefaultTimestampValidator::getFreshnessAndSkewAdjustedDate”);

return c.getTime();

}

private static Date getGMTDateWithSkewAdjusted(Calendar c,

long maxClockSkew, boolean addSkew) {

System.out

.println(“Enterd::DefaultTimestampValidator::getGMTDateWithSkewAdjusted”);

long offset = c.get(Calendar.ZONE_OFFSET);

if (c.getTimeZone().inDaylightTime(c.getTime())) {

offset += c.getTimeZone().getDSTSavings();

}

long beforeTime = c.getTimeInMillis();

long currentTime = beforeTime – offset;

if (addSkew)

currentTime = currentTime + maxClockSkew;

else

currentTime = currentTime – maxClockSkew;

c.setTimeInMillis(currentTime);

System.out

.println(“Leaving::DefaultTimestampValidator::getGMTDateWithSkewAdjusted”);

return c.getTime();

}

private class X509CertificateValidatorImpl implements

CertificateValidationCallback.CertificateValidator {

public boolean validate(X509Certificate certificate)

throws CertificateValidationCallback.CertificateValidationException {

System.out

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

26 of 67 6/22/2011 2:07 PM

Page 27: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.println(“Enterd::X509CertificateValidatorImpl::validate”);

if (isSelfCert(certificate)) {

System.out

.println(“Leaving::X509CertificateValidatorImpl::validate::1″);

return true;

}

try {

certificate.checkValidity();

} catch (CertificateExpiredException e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

“X509Certificate Expired”, e);

} catch (CertificateNotYetValidException e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

“X509Certificate not yet valid”, e);

}

X509CertSelector certSelector = new X509CertSelector();

certSelector.setCertificate(certificate);

PKIXBuilderParameters parameters;

CertPathBuilder builder;

try {

parameters = new PKIXBuilderParameters(trustStore, certSelector);

parameters.setRevocationEnabled(false);

builder = CertPathBuilder.getInstance(“PKIX”);

} catch (Exception e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

27 of 67 6/22/2011 2:07 PM

Page 28: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

e.getMessage(), e);

}

try {

PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder

.build(parameters);

} catch (Exception e) {

e.printStackTrace();

System.out

.println(“Leaving::X509CertificateValidatorImpl::validate::2″);

return false;

}

System.out

.println(“Leaving::X509CertificateValidatorImpl::validate::3″);

return true;

}

private boolean isSelfCert(X509Certificate cert)

throws CertificateValidationCallback.CertificateValidationException {

System.out

.println(“Entered::X509CertificateValidatorImpl::isSelfCert”);

try {

if (keyStore == null)

initKeyStore();

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (keyStore.isKeyEntry(alias)) {

X509Certificate x509Cert = (X509Certificate) keyStore

.getCertificate(alias);

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

28 of 67 6/22/2011 2:07 PM

Page 29: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

if (x509Cert != null) {

if (x509Cert.equals(cert))

System.out

.println(“Leaving::X509CertificateValidatorImpl::isSelfCert::1″);

return true;

}

}

}

System.out

.println(“Leaving::X509CertificateValidatorImpl::isSelfCert::2″);

return false;

} catch (Exception e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

e.getMessage(), e);

}

}

}

private String getContainerHome() {

System.out

.println(“Entered::X509CertificateValidatorImpl::getContainerHome”);

String _home = “”;

String fileSeparator = System.getProperty(“file.separator”);

String contHome = System.getProperty(“catalina.home”);

if (contHome != null) {

String isAS = System.getProperty(“com.sun.aas.instanceRoot”);

if (isAS != null) {

_home = contHome + fileSeparator + “..” + fileSeparator + “..”;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

29 of 67 6/22/2011 2:07 PM

Page 30: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

} else {

_home = contHome;

}

} else {

_home = System.getProperty(“jwsdp.home”);

if (_home == null) {

_home = System.getProperty(“as.home”);

}

}

System.out

.println(“Leaving::X509CertificateValidatorImpl::getContainerHome”);

return _home;

}

}

Step 11: Create Interceptor class to handle soap requests ValidateUserTokenInterceptor.java.

package com.sungard.cxf.example.server;

import java.util.Vector;

import org.apache.cxf.message.Message;

import org.apache.cxf.phase.AbstractPhaseInterceptor;

import org.apache.cxf.phase.Phase;

import org.apache.ws.security.WSSecurityEngineResult;

import org.apache.ws.security.WSUsernameTokenPrincipal;

import org.apache.ws.security.handler.WSHandlerConstants;

import org.apache.ws.security.handler.WSHandlerResult;

public class ValidateUserTokenInterceptor extends AbstractPhaseInterceptor {

public ValidateUserTokenInterceptor(String s) {

super(s);

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

30 of 67 6/22/2011 2:07 PM

Page 31: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

public ValidateUserTokenInterceptor() {

super(Phase.UNMARSHAL);

}

public void handleMessage(Message message) {

System.out

.println(“Enterd ValidateUserTokenInterceptor::handleMessage”);

boolean userTokenValidated = false;

Vector result = (Vector) message

.getContextualProperty(WSHandlerConstants.RECV_RESULTS);

for (int i = 0; i < result.size(); i++) {

WSHandlerResult res = (WSHandlerResult) result.get(i);

for (int j = 0; j < res.getResults().size(); j++) {

WSSecurityEngineResult secRes = (WSSecurityEngineResult) res

.getResults().get(j);

if (secRes.getPrincipal() != null) {

System.out

.println(“ValidateUserTokenInterceptor::handleMessage::Class”

+ secRes.getPrincipal().getClass());

System.out

.println(“ValidateUserTokenInterceptor::handleMessage::ClassName”

+ secRes.getPrincipal().getClass()

.getName());

System.out

.println(“ValidateUserTokenInterceptor::handleMessage::Name”

+ secRes.getPrincipal().getName());

if (secRes.getPrincipal().getClass().getName().equals(

“org.apache.ws.security.WSUsernameTokenPrincipal”)) {

System.out

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

31 of 67 6/22/2011 2:07 PM

Page 32: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.println(“ValidateUserTokenInterceptor::handleMessage::WSUsernameTokenPrincipal”

+ secRes.getPrincipal().getName());

WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes

.getPrincipal();

System.out.println(“principal.isPasswordDigest”

+ principal.isPasswordDigest());

System.out.println(“principal.getNonce()”

+ principal.getNonce());

System.out.println(“principal.getPassword()”

+ principal.getPassword());

System.out.println(“principal.getCreatedTime()”

+ principal.getCreatedTime());

if (principal.getPassword() == null) {

throw new RuntimeException(

“Invalid Security Header”);

} else {

System.out

.println(“ValidateUserTokenInterceptor::handleMessage::userTokenValidated = true”);

userTokenValidated = true;

}

}

}

}

}

if (!userTokenValidated) {

throw new RuntimeException(“Security processing failed::Peter”);

}

System.out

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

32 of 67 6/22/2011 2:07 PM

Page 33: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.println(“Leaving ValidateUserTokenInterceptor::handleMessage”);

}

}

Step 12: Create beans.xml file to setup the application context for the server.

<?xml version=”1.0″ encoding=”UTF-8″?>

<beans xmlns=”http://www.springframework.org/schema/beans”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xmlns:jaxws=”http://cxf.apache.org/jaxws”

xsi:schemaLocation=”

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd”>

<import resource=”classpath:META-INF/cxf/cxf.xml” />

<import resource=”classpath:META-INF/cxf/cxf-extension-soap.xml” />

<import resource=”classpath:META-INF/cxf/cxf-servlet.xml” />

<jaxws:endpoint id=”helloWorld”

implementor=”com.sungard.cxf.example.server.IHello_Impl”

address=”/HelloService”>

<jaxws:inInterceptors>

<bean id=”logIn”

/>

<bean id=”logOut”

/>

<bean

/>

<bean

>

<property name=”properties”>

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

33 of 67 6/22/2011 2:07 PM

Page 34: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

<map>

<entry key=”action”

value=”UsernameToken SAMLTokenUnsigned” />

<entry key=”passwordType” value=”PasswordText” />

<entry key=”enableNamespacePrefixOptimization”

value=”true” />

<entry key=”disablePrettyXML” value=”true” />

<entry key=”sendXsiTypes” value=”true” />

<entry key=”sendMultiRefs” value=”true” />

<entry key=”sendXMLDeclaration” value=”true” />

<entry key=”passwordCallbackClass”

value=”com.sungard.cxf.example.server.ServerSecurityEnvironmentHandler” />

<entry key=”signaturePropFile”

value=”server_sign.properties”>

</entry>

</map>

</property>

</bean>

<bean

/>

</jaxws:inInterceptors>

</jaxws:endpoint>

</beans>

Step 13: Create server_sign.properties under WEB-INF\classes folder to mention private keystore file details.

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin

org.apache.ws.security.crypto.merlin.keystore.type=jks

org.apache.ws.security.crypto.merlin.keystore.password=changeit

org.apache.ws.security.crypto.merlin.file=server-keystore.jks

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

34 of 67 6/22/2011 2:07 PM

Page 35: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Step 14: Copy all keystore and certificate files under WEB-INF\classes folder.

Step 15: Create web.xml file

<?xml version=”1.0″ encoding=”ISO-8859-1″?>

<!DOCTYPE web-app

PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”

“http://java.sun.com/dtd/web-app_2_3.dtd”>

<web-app>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>WEB-INF/beans.xml</param-value>

</context-param>

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<servlet>

<servlet-name>CXFServlet</servlet-name>

<display-name>CXF Servlet</display-name>

<servlet-class>

org.apache.cxf.transport.servlet.CXFServlet

</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>CXFServlet</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

35 of 67 6/22/2011 2:07 PM

Page 36: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

</web-app>

Step 16: Create ant folder inside project. And Create build.xml file inside ant folder.

<?xml version=”1.0″ encoding=”UTF-8″?>

<project basedir=”../” default=”archive”>

<target name=”archive”>

<jar destfile=”samlnormalsecurity.war”>

<fileset dir=”${basedir}”>

<include name=”**/*.class” />

<include name=”**/*.jks*” />

<include name=”**/*.properties*” />

</fileset>

<fileset dir=”${basedir}”>

<include name=”**/*.jar” />

</fileset>

<fileset dir=”${basedir}”>

<include name=”**/*.xml” />

<exclude name=”**/*build*” />

</fileset>

</jar>

</target>

</project>

Step 17: Run build.xml using Ant.

Step 18: Deploy samlnormalsecurity.war into Web/Application Server (Tomcat/JBoss).

Step 19: Verify application deployed successfully or by using following url.

http://localhost:8080/samlnormalsecurity/HelloService?wsdl

Step 20: Browser will show wsdl file our web service.

Creating Client Application.

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

36 of 67 6/22/2011 2:07 PM

Page 37: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Step 1: Create New Java project in Eclipse

Step 2: Create folder Structure as like above application

Step 3: Use same jar files used for Server application.

Step 4: Set all the jars files into classpath.

Step 5: Create Remote Interface in client (IHello.java) (You can use wsdl2java for creating same)

package com.sungard.cxf.example.server;

import javax.jws.WebService;

@WebService

public interface IHello {

public String sayHello(String value);

}

Step 6: Create ClientSecurityEnvironmentHandler.java for handling soap request in client side. Here you have

set the password what you are given client alias. You have tomention client ketstore passwords also here.

private String keyStorePassword = “changeit”;

private String trustStorePassword = “changeit”;

else if (callbacks[i] instanceof WSPasswordCallback) {

WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];

System.out.println(“cb.getPassword()” + cb.getPassword());

cb.setPassword(“changeit”);

}

package com.sungard.cxf.example.server;

import java.io.IOException;

import java.math.BigInteger;

import java.net.URL;

import java.security.KeyStore;

import java.security.PrivateKey;

import java.security.cert.CertPathBuilder;

import java.security.cert.Certificate;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

37 of 67 6/22/2011 2:07 PM

Page 38: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

import java.security.cert.CertificateExpiredException;

import java.security.cert.CertificateNotYetValidException;

import java.security.cert.PKIXBuilderParameters;

import java.security.cert.PKIXCertPathBuilderResult;

import java.security.cert.X509CertSelector;

import java.security.cert.X509Certificate;

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.Calendar;

import java.util.Date;

import java.util.Enumeration;

import java.util.GregorianCalendar;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.UnsupportedCallbackException;

import javax.xml.ws.BindingProvider;

import org.apache.ws.security.WSPasswordCallback;

import com.sun.xml.wss.impl.callback.CertificateValidationCallback;

import com.sun.xml.wss.impl.callback.DecryptionKeyCallback;

import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;

import com.sun.xml.wss.impl.callback.PasswordCallback;

import com.sun.xml.wss.impl.callback.PasswordValidationCallback;

import com.sun.xml.wss.impl.callback.SignatureKeyCallback;

import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;

import com.sun.xml.wss.impl.callback.TimestampValidationCallback;

import com.sun.xml.wss.impl.callback.UsernameCallback;

import com.sun.xml.wss.impl.misc.SecurityUtil;

/**

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

38 of 67 6/22/2011 2:07 PM

Page 39: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

* A sample implementation of a CallbackHandler.

*/

public class ClientSecurityEnvironmentHandler implements CallbackHandler {

private KeyStore keyStore;

private KeyStore trustStore;

private String keyStorePassword = “changeit”;

private String trustStorePassword = “changeit”;

private static final UnsupportedCallbackException unsupported = new UnsupportedCallbackException(

null, “Unsupported Callback Type Encountered”);

public ClientSecurityEnvironmentHandler() throws Exception {

System.out.println(“Entered::ClientSecurityEnvironmentHandler”);

initTrustStore();

initKeyStore();

System.out.println(“Leaving::ClientSecurityEnvironmentHandler”);

}

public void handle(Callback[] callbacks) throws IOException,

UnsupportedCallbackException {

System.out.println(“Entered::ClientSecurityEnvironmentHandler::handle”);

for (int i = 0; i < callbacks.length; i++) {

if (callbacks[i] instanceof PasswordValidationCallback) {

PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];

if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {

cb.setValidator(new PlainTextPasswordValidator());

} else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {

PasswordValidationCallback.DigestPasswordRequest request =(PasswordValidationCallback.DigestPasswordRequest) cb

.getRequest();

String username = request.getUsername();

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

39 of 67 6/22/2011 2:07 PM

Page 40: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

if (“Ron”.equals(username)) {

request.setPassword(“noR”);

cb

.setValidator(new PasswordValidationCallback.DigestPasswordValidator());

}

} else {

System.out

.println(“ClientSecurityEnvironmentHandler::Handle::1″);

throw unsupported;

}

} else if (callbacks[i] instanceof TimestampValidationCallback) {

TimestampValidationCallback cb = (TimestampValidationCallback) callbacks[i];

cb.setValidator(new DefaultTimestampValidator());

} else if (callbacks[i] instanceof SignatureVerificationKeyCallback) {

SignatureVerificationKeyCallback cb = (SignatureVerificationKeyCallback) callbacks[i];

if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) {

// subject keyid request

SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request =

(SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb

.getRequest();

X509Certificate cert = getCertificateFromTrustStore(request

.getSubjectKeyIdentifier());

request.setX509Certificate(cert);

} else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) {

// issuer serial request

SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request =

(SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) cb

.getRequest();

X509Certificate cert = getCertificateFromTrustStore(request

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

40 of 67 6/22/2011 2:07 PM

Page 41: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.getIssuerName(), request.getSerialNumber());

request.setX509Certificate(cert);

} else {

System.out

.println(“ClientSecurityEnvironmentHandler::Handle::2″);

throw unsupported;

}

} else if (callbacks[i] instanceof SignatureKeyCallback) {

SignatureKeyCallback cb = (SignatureKeyCallback) callbacks[i];

if (cb.getRequest() instanceof SignatureKeyCallback.DefaultPrivKeyCertRequest) {

// default priv key cert req

SignatureKeyCallback.DefaultPrivKeyCertRequest request =

(SignatureKeyCallback.DefaultPrivKeyCertRequest) cb

.getRequest();

getDefaultPrivKeyCert(request);

} else if (cb.getRequest() instanceof SignatureKeyCallback.AliasPrivKeyCertRequest) {

SignatureKeyCallback.AliasPrivKeyCertRequest request =

(SignatureKeyCallback.AliasPrivKeyCertRequest) cb

.getRequest();

String alias = request.getAlias();

try {

X509Certificate cert = (X509Certificate) keyStore

.getCertificate(alias);

request.setX509Certificate(cert);

// Assuming key passwords same as the keystore password

PrivateKey privKey = (PrivateKey) keyStore.getKey(

alias, keyStorePassword.toCharArray());

request.setPrivateKey(privKey);

} catch (Exception e) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

41 of 67 6/22/2011 2:07 PM

Page 42: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

throw new IOException(e.getMessage());

}

} else {

System.out

.println(“ClientSecurityEnvironmentHandler::Handle::3″);

throw unsupported;

}

} else if (callbacks[i] instanceof DecryptionKeyCallback) {

DecryptionKeyCallback cb = (DecryptionKeyCallback) callbacks[i];

if (cb.getRequest() instanceof DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) {

DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request =

(DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb

.getRequest();

byte[] ski = request.getSubjectKeyIdentifier();

PrivateKey privKey = getPrivateKey(ski);

request.setPrivateKey(privKey);

} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBasedRequest) {

DecryptionKeyCallback.X509IssuerSerialBasedRequest request =

(DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb

.getRequest();

String issuerName = request.getIssuerName();

BigInteger serialNumber = request.getSerialNumber();

PrivateKey privKey = getPrivateKey(issuerName, serialNumber);

request.setPrivateKey(privKey);

} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBasedRequest) {

DecryptionKeyCallback.X509CertificateBasedRequest request =

(DecryptionKeyCallback.X509CertificateBasedRequest) cb

.getRequest();

X509Certificate cert = request.getX509Certificate();

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

42 of 67 6/22/2011 2:07 PM

Page 43: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

PrivateKey privKey = getPrivateKey(cert);

request.setPrivateKey(privKey);

} else {

System.out

.println(“ClientSecurityEnvironmentHandler::Handle::4″);

throw unsupported;

}

} else if (callbacks[i] instanceof EncryptionKeyCallback) {

EncryptionKeyCallback cb = (EncryptionKeyCallback) callbacks[i];

if (cb.getRequest() instanceof EncryptionKeyCallback.AliasX509CertificateRequest) {

EncryptionKeyCallback.AliasX509CertificateRequest request =

(EncryptionKeyCallback.AliasX509CertificateRequest) cb

.getRequest();

String alias = request.getAlias();

if (alias == null) {

// plugin code here to read the cert from the

// ThreadLocal

} else {

try {

X509Certificate cert = (X509Certificate) trustStore

.getCertificate(alias);

request.setX509Certificate(cert);

} catch (Exception e) {

throw new IOException(e.getMessage());

}

}

} else {

System.out

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

43 of 67 6/22/2011 2:07 PM

Page 44: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

.println(“ClientSecurityEnvironmentHandler::Handle::5″);

throw unsupported;

}

} else if (callbacks[i] instanceof CertificateValidationCallback) {

CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];

cb.setValidator(new X509CertificateValidatorImpl());

} else if (callbacks[i] instanceof UsernameCallback) {

UsernameCallback cb = (UsernameCallback) callbacks[i];

String username = (String) cb.getRuntimeProperties().get(

BindingProvider.USERNAME_PROPERTY);

System.out.println(“Got Username……… : ” + username);

cb.setUsername(username);

} else if (callbacks[i] instanceof PasswordCallback) {

PasswordCallback cb = (PasswordCallback) callbacks[i];

String password = (String) cb.getRuntimeProperties().get(

BindingProvider.PASSWORD_PROPERTY);

System.out.println(“Got Password……… : ” + password);

cb.setPassword(password);

} else if (callbacks[i] instanceof WSPasswordCallback) {

WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];

System.out.println(“cb.getPassword()” + cb.getPassword());

cb.setPassword(“changeit”);

} else {

System.out.println(callbacks[i].getClass().getName());

System.out

.println(“ClientSecurityEnvironmentHandler::Handle::6″);

throw unsupported;

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

44 of 67 6/22/2011 2:07 PM

Page 45: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

}

private void initTrustStore() throws IOException {

try {

URL truststoreURL = SecurityUtil

.loadFromClasspath(“client-truststore.jks”);

trustStore = KeyStore.getInstance(“JKS”);

trustStore.load(truststoreURL.openStream(), trustStorePassword

.toCharArray());

} catch (Exception e) {

throw new IOException(e.getMessage());

}

}

private void initKeyStore() throws IOException {

try {

URL keystoreURL = SecurityUtil

.loadFromClasspath(“client-keystore.jks”);

keyStore = KeyStore.getInstance(“JKS”);

keyStore.load(keystoreURL.openStream(), keyStorePassword

.toCharArray());

} catch (Exception e) {

throw new IOException(e.getMessage());

}

}

private X509Certificate getCertificateFromTrustStore(byte[] ski)

throws IOException {

try {

Enumeration aliases = trustStore.aliases();

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

45 of 67 6/22/2011 2:07 PM

Page 46: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

Certificate cert = trustStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

byte[] keyId = getSubjectKeyIdentifier(x509Cert);

if (keyId == null) {

// Cert does not contain a key identifier

continue;

}

if (Arrays.equals(ski, keyId)) {

return x509Cert;

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

return null;

}

private X509Certificate getCertificateFromTrustStore(String issuerName,

BigInteger serialNumber) throws IOException {

try {

Enumeration aliases = trustStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

Certificate cert = trustStore.getCertificate(alias);

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

46 of 67 6/22/2011 2:07 PM

Page 47: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

X509Certificate x509Cert = (X509Certificate) cert;

String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser

.normalize(x509Cert.getIssuerDN().getName());

BigInteger thisSerialNumber = x509Cert.getSerialNumber();

if (thisIssuerName.equals(issuerName)

&& thisSerialNumber.equals(serialNumber)) {

return x509Cert;

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

return null;

}

public PrivateKey getPrivateKey(byte[] ski) throws IOException {

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

47 of 67 6/22/2011 2:07 PM

Page 48: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

X509Certificate x509Cert = (X509Certificate) cert;

byte[] keyId = getSubjectKeyIdentifier(x509Cert);

if (keyId == null) {

// Cert does not contain a key identifier

continue;

}

if (Arrays.equals(ski, keyId)) {

// Asuumed key password same as the keystore password

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

return null;

}

public PrivateKey getPrivateKey(String issuerName, BigInteger serialNumber)

throws IOException {

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert == null || !”X.509″.equals(cert.getType())) {

continue;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

48 of 67 6/22/2011 2:07 PM

Page 49: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

X509Certificate x509Cert = (X509Certificate) cert;

String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser

.normalize(x509Cert.getIssuerDN().getName());

BigInteger thisSerialNumber = x509Cert.getSerialNumber();

if (thisIssuerName.equals(issuerName)

&& thisSerialNumber.equals(serialNumber)) {

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

}

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

return null;

}

public PrivateKey getPrivateKey(X509Certificate certificate)

throws IOException {

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String alias = (String) aliases.nextElement();

if (!keyStore.isKeyEntry(alias))

continue;

Certificate cert = keyStore.getCertificate(alias);

if (cert != null && cert.equals(certificate))

return (PrivateKey) keyStore.getKey(alias, keyStorePassword

.toCharArray());

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

49 of 67 6/22/2011 2:07 PM

Page 50: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

return null;

}

private void getDefaultPrivKeyCert(

SignatureKeyCallback.DefaultPrivKeyCertRequest request)

throws IOException {

String uniqueAlias = null;

try {

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

String currentAlias = (String) aliases.nextElement();

if (keyStore.isKeyEntry(currentAlias)) {

Certificate thisCertificate = keyStore

.getCertificate(currentAlias);

if (thisCertificate != null) {

if (thisCertificate instanceof X509Certificate) {

if (uniqueAlias == null) {

uniqueAlias = currentAlias;

} else {

// Not unique!

uniqueAlias = null;

break;

}

}

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

50 of 67 6/22/2011 2:07 PM

Page 51: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

}

if (uniqueAlias != null) {

request.setX509Certificate((X509Certificate) keyStore

.getCertificate(uniqueAlias));

request.setPrivateKey((PrivateKey) keyStore.getKey(uniqueAlias,

keyStorePassword.toCharArray()));

}

} catch (Exception e) {

throw new IOException(e.getMessage());

}

}

private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {

String SUBJECT_KEY_IDENTIFIER_OID = “2.5.29.14″;

byte[] subjectKeyIdentifier = cert

.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);

if (subjectKeyIdentifier == null)

return null;

try {

sun.security.x509.KeyIdentifier keyId = null;

sun.security.util.DerValue derVal = new sun.security.util.DerValue(

new sun.security.util.DerInputStream(subjectKeyIdentifier)

.getOctetString());

keyId = new sun.security.x509.KeyIdentifier(derVal.getOctetString());

return keyId.getIdentifier();

} catch (NoClassDefFoundError ncde) {

if (subjectKeyIdentifier == null)

return null;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

51 of 67 6/22/2011 2:07 PM

Page 52: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

byte[] dest = new byte[subjectKeyIdentifier.length - 4];

System.arraycopy(subjectKeyIdentifier, 4, dest, 0,

subjectKeyIdentifier.length – 4);

return dest;

} catch (java.io.IOException ex) {

// ignore

return null;

}

}

private class PlainTextPasswordValidator implements

PasswordValidationCallback.PasswordValidator {

public boolean validate(PasswordValidationCallback.Request request)

throws PasswordValidationCallback.PasswordValidationException {

PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest =

(PasswordValidationCallback.PlainTextPasswordRequest) request;

if (“Ron”.equals(plainTextRequest.getUsername())

&& “noR”.equals(plainTextRequest.getPassword())) {

return true;

}

return false;

}

}

private class DefaultTimestampValidator implements

TimestampValidationCallback.TimestampValidator {

public void validate(TimestampValidationCallback.Request request)

throws TimestampValidationCallback.TimestampValidationException {

// validate timestamp creation and expiration time.

TimestampValidationCallback.UTCTimestampRequest utcTimestampRequest =(TimestampValidationCallback.UTCTimestampRequest) request;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

52 of 67 6/22/2011 2:07 PM

Page 53: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(

“yyyy-MM-dd’T'HH:mm:ss’Z'”);

SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(

“yyyy-MM-dd’T'HH:mm:ss’.'SSS’Z'”);

Date created = null;

Date expired = null;

try {

try {

created = calendarFormatter1.parse(utcTimestampRequest

.getCreated());

if (utcTimestampRequest.getExpired() != null)

expired = calendarFormatter1.parse(utcTimestampRequest

.getExpired());

} catch (java.text.ParseException pe) {

created = calendarFormatter2.parse(utcTimestampRequest

.getCreated());

if (utcTimestampRequest.getExpired() != null)

expired = calendarFormatter2.parse(utcTimestampRequest

.getExpired());

}

} catch (java.text.ParseException pe) {

throw new TimestampValidationCallback.TimestampValidationException(

pe.getMessage());

}

long maxClockSkew = utcTimestampRequest.getMaxClockSkew();

long timestampFreshnessLimit = utcTimestampRequest

.getTimestampFreshnessLimit();

// validate creation time

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

53 of 67 6/22/2011 2:07 PM

Page 54: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

validateCreationTime(created, maxClockSkew, timestampFreshnessLimit);

// validate expiration time

if (expired != null)

validateExpirationTime(expired, maxClockSkew,

timestampFreshnessLimit);

}

}

public void validateExpirationTime(Date expires, long maxClockSkew,

long timestampFreshnessLimit)

throws TimestampValidationCallback.TimestampValidationException {

// System.out.println(“Validate Expiration time called”);

Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),

maxClockSkew, false);

if (expires.before(currentTime)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The current time is ahead of the expiration time in Timestamp”);

}

}

public void validateCreationTime(Date created, long maxClockSkew,

long timestampFreshnessLimit)

throws TimestampValidationCallback.TimestampValidationException {

// System.out.println(“Validate Creation time called”);

Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,

timestampFreshnessLimit);

if (created.before(current)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The creation time is older than “

+ ” currenttime – timestamp-freshness-limit – max-clock-skew”);

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

54 of 67 6/22/2011 2:07 PM

Page 55: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),

maxClockSkew, true);

if (currentTime.before(created)) {

throw new TimestampValidationCallback.TimestampValidationException(

“The creation time is ahead of the current time.”);

}

}

private static Date getFreshnessAndSkewAdjustedDate(long maxClockSkew,

long timestampFreshnessLimit) {

Calendar c = new GregorianCalendar();

long offset = c.get(Calendar.ZONE_OFFSET);

if (c.getTimeZone().inDaylightTime(c.getTime())) {

offset += c.getTimeZone().getDSTSavings();

}

long beforeTime = c.getTimeInMillis();

long currentTime = beforeTime – offset;

long adjustedTime = currentTime – maxClockSkew

- timestampFreshnessLimit;

c.setTimeInMillis(adjustedTime);

return c.getTime();

}

private static Date getGMTDateWithSkewAdjusted(Calendar c,

long maxClockSkew, boolean addSkew) {

long offset = c.get(Calendar.ZONE_OFFSET);

if (c.getTimeZone().inDaylightTime(c.getTime())) {

offset += c.getTimeZone().getDSTSavings();

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

55 of 67 6/22/2011 2:07 PM

Page 56: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

long beforeTime = c.getTimeInMillis();

long currentTime = beforeTime – offset;

if (addSkew)

currentTime = currentTime + maxClockSkew;

else

currentTime = currentTime – maxClockSkew;

c.setTimeInMillis(currentTime);

return c.getTime();

}

private class X509CertificateValidatorImpl implements

CertificateValidationCallback.CertificateValidator {

public boolean validate(X509Certificate certificate)

throws CertificateValidationCallback.CertificateValidationException {

if (isSelfCert(certificate)) {

return true;

}

try {

certificate.checkValidity();

} catch (CertificateExpiredException e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

“X509Certificate Expired”, e);

} catch (CertificateNotYetValidException e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

“X509Certificate not yet valid”, e);

}

X509CertSelector certSelector = new X509CertSelector();

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

56 of 67 6/22/2011 2:07 PM

Page 57: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

certSelector.setCertificate(certificate);

PKIXBuilderParameters parameters;

CertPathBuilder builder;

try {

parameters = new PKIXBuilderParameters(trustStore, certSelector);

parameters.setRevocationEnabled(false);

builder = CertPathBuilder.getInstance(“PKIX”);

} catch (Exception e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

e.getMessage(), e);

}

try {

PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder

.build(parameters);

} catch (Exception e) {

e.printStackTrace();

return false;

}

return true;

}

private boolean isSelfCert(X509Certificate cert)

throws CertificateValidationCallback.CertificateValidationException {

try {

if (keyStore == null)

initKeyStore();

Enumeration aliases = keyStore.aliases();

while (aliases.hasMoreElements()) {

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

57 of 67 6/22/2011 2:07 PM

Page 58: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

String alias = (String) aliases.nextElement();

if (keyStore.isKeyEntry(alias)) {

X509Certificate x509Cert = (X509Certificate) keyStore

.getCertificate(alias);

if (x509Cert != null) {

if (x509Cert.equals(cert))

return true;

}

}

}

return false;

} catch (Exception e) {

e.printStackTrace();

throw new CertificateValidationCallback.CertificateValidationException(

e.getMessage(), e);

}

}

}

private String getContainerHome() {

String _home = “”;

String fileSeparator = System.getProperty(“file.separator”);

String contHome = System.getProperty(“catalina.home”);

if (contHome != null) {

String isAS = System.getProperty(“com.sun.aas.instanceRoot”);

if (isAS != null) {

_home = contHome + fileSeparator + “..” + fileSeparator + “..”;

} else {

_home = contHome;

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

58 of 67 6/22/2011 2:07 PM

Page 59: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

}

} else {

_home = System.getProperty(“jwsdp.home”);

if (_home == null) {

_home = System.getProperty(“as.home”);

}

}

return _home;

}

}

Step 7: Create the service factory (AuthServiceFactory.java), which is extremely easy since all the work was

done in the Spring file:

package com.sungard.cxf.example.server;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class AuthServiceFactory {

private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(

new String[] { “cxfClient.xml” });

public AuthServiceFactory() {

}

public IHello getService() {

return (IHello) context.getBean(“client”);

}

}

Step 8: Create Client.java to invoke the service.

package com.sungard.cxf.example.server;

public final class Client {

private Client() {

}

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

59 of 67 6/22/2011 2:07 PM

Page 60: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

public static void main(String args[]) throws Exception {

AuthServiceFactory af = new AuthServiceFactory();

IHello client1 = af.getService();

String response1 = client1.sayHello(“Hello”);

System.out.println(“Response: ” + response1);

}

}

Step 9: Create cxfClient.xml to setup the application context for the client.

<?xml version=”1.0″ encoding=”UTF-8″?>

<beans xmlns=”http://www.springframework.org/schema/beans”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xmlns:jaxws=”http://cxf.apache.org/jaxws”

xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd”>

<bean id=”proxyFactory”

>

<property name=”serviceClass”

value=”com.sungard.cxf.example.server.IHello” />

<property name=”address”

value=”http://localhost:8080/samlnormalsecurity/HelloService” />

<property name=”inInterceptors”>

<list>

<ref bean=”logIn” />

</list>

</property>

<property name=”outInterceptors”>

<list>

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

60 of 67 6/22/2011 2:07 PM

Page 61: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

<ref bean=”logOut” />

<ref bean=”saajOut” />

<ref bean=”wss4jOut” />

</list>

</property>

</bean>

<bean id=”client”

factory-bean=”proxyFactory” factory-method=”create” />

<bean id=”logIn”

/>

<bean id=”logOut”

/>

<bean id=”saajOut”

/>

<bean id=”wss4jOut”

>

<constructor-arg>

<map>

<entry key=”action” value=”UsernameToken SAMLTokenUnsigned” />

<entry key=”user” value=”xws-security-client” />

<entry key=”passwordType” value=”PasswordText” />

<entry key=”samlPropFile” value=”saml2.properties”/>

<entry key=”enableNamespacePrefixOptimization” value=”true”/>

<entry key=”disablePrettyXML” value=”true”/>

<entry key=”sendXsiTypes” value=”true”/>

<entry key=”sendMultiRefs” value=”true”/>

<entry key=”sendXMLDeclaration” value=”true”/>

<entry key=”passwordCallbackClass”

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

61 of 67 6/22/2011 2:07 PM

Page 62: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

value=”com.sungard.cxf.example.server.ClientSecurityEnvironmentHandler” />

</map>

</constructor-arg>

</bean>

</beans>

Step 11: Create client_sign.properties file under WEB-INF\classes folder. To give public keystore file details.

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin

org.apache.ws.security.crypto.merlin.keystore.type=jks

org.apache.ws.security.crypto.merlin.keystore.password=changeit

org.apache.ws.security.crypto.merlin.keystore.alias=xws-security-client

org.apache.ws.security.crypto.merlin.file=client-keystore.jks

Step 12: Create saml2.properties file under WEB-INF\classes folder. To give public keystore file details.

org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.SAMLIssuerImpl

org.apache.ws.security.saml.issuer.cryptoProp.file=client_sign.properties

org.apache.ws.security.saml.issuer=www.example.com

org.apache.ws.security.saml.subjectNameId.name=xws-security-client

org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com

org.apache.ws.security.saml.authenticationMethod=password

org.apache.ws.security.saml.confirmationMethod=senderVouches

org.apache.ws.security.saml.issuer.key.name=xws-security-client

org.apache.ws.security.saml.issuer.key.password=changeit

Step 13: Copy keystore and certificates in WEB-INF\classes folder. (Or set it in classpath)

Step 14: Run Client.java

You will get response like as follows.

Response: You SaidHello

Note:

Client Side:

We Set User name in client cxfClient.xml file. That is public alias name. (We can set the same through

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

62 of 67 6/22/2011 2:07 PM

Page 63: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

program also and we can read it xml/properties files. We can pass the same in runtime also)

<entry key=”user” value=”xws-security-client” />

We Set password in ClientSecurityEnvironmentHandler.java class (We can pass same in runtime also)

// set the password for our message.

pc.setPassword(“changeit”);

You can see the In & Outbound Messages in Client Side. As like as follows. This will go with signature.

INFO: Outbound Message

—————————

Encoding: UTF-8

Headers: {SOAPAction=[""], Accept=[*]}

Messages:

Payload: <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>

<soap:Header>

<wsse:Security xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-

1.0.xsd” soap:mustUnderstand=”1″><Assertion xmlns=”urn:oasis:names:tc:SAML:1.0:assertion”

xmlns:saml=”urn:oasis:names:tc:SAML:1.0:assertion” xmlns:samlp=”urn:oasis:names:tc:SAML:1.0:protocol”AssertionID=”b58cef8ed07e7a8c1be2d099e73ba075″ IssueInstant=”2008-04-04T05:13:59.068Z”

Issuer=”www.example.com” MajorVersion=”1″ MinorVersion=”1″><AuthenticationStatement

AuthenticationInstant=”2008-04-04T05:13:58.896Z”AuthenticationMethod=”urn:oasis:names:tc:SAML:1.0:am:password”><Subject><NameIdentifier

NameQualifier=”www.example.com”>xws-security-client</NameIdentifier><SubjectConfirmation>

<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</ConfirmationMethod></SubjectConfirmation></Subject></AuthenticationStatement></Assertion><wsse:UsernameToken

xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”

wsu:Id=”UsernameToken-24451742″ xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”><wsse:Username xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-

200401-wss-wssecurity-secext-1.0.xsd”>xws-security-client</wsse:Username><wsse:Password

Type=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText”xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-

1.0.xsd”>changeit</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body>

<ns1:sayHello xmlns:ns1=”http://server.example.cxf.sungard.com/”><arg0>Hello</arg0></ns1:sayHello></soap:Body></soap:Envelope>

————————————–

Apr 4, 2008 10:44:10 AM org.apache.cxf.interceptor.LoggingInInterceptor logging

INFO: Inbound Message

—————————-

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

63 of 67 6/22/2011 2:07 PM

Page 64: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Share this: Facebook Print Email

Like Be the first to like this post.

Encoding: UTF-8

Headers: {Content-Length=[230], Date=[Fri, 04 Apr 2008 05:14:10 GMT], SOAPAction=[""], Server=

[Apache-Coyote/1.1], content-type=[text/xml;charset=UTF-8]}

Messages:

Message:

Payload: <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”><soap:Body>

<ns1:sayHelloResponse xmlns:ns1=”http://server.example.cxf.sungard.com/”><return>YouSaidHello</return></ns1:sayHelloResponse></soap:Body></soap:Envelope>

————————————–

September 4, 2009 - Posted by Peter Arockiaraj | Web Services

2 Comments »

Hi Peter,

Excellent Article, good work….

Can u able to share the working source code for me ?…….

Thanks & Regards,

Ibrahim

Comment by Ibrahim | November 26, 2010 | Reply

1.

Hi Peter,2.

Ads by Google

Download Google

Chrome

Searching is fast and easy with Google'sweb browser.

www.Google.com/Chrome

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

64 of 67 6/22/2011 2:07 PM

Page 65: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Notify me of follow-up comments via email.

Notify me of new posts via email.

Post Comment

Good Article!!

Can you send me the source code?

Regards,

Gerard

Comment by Gerard | March 11, 2011 | Reply

Leave a Reply

« Previous | Next »

About Me

Log In Log In Log In

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

65 of 67 6/22/2011 2:07 PM

Page 66: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Share this: Facebook Print Email

Peter has over 8 years of experience & has worked in several roles. Working

in Professional services Team in SunGard Technology Services. He is Technical Consultant in customization

team.

He started his career in SoftTech Ltd & as Software Engineer. And worked in leading software organizations

like GoRemote/iPass, Satyam and now in Sungard.

He holds a Master degree in Science from Madurai Kamaraj University.

More details about Peter can be viewed at http://www.linkedin.com/in/peterarockiaraj. Peter is currently in

India and can be reached on his email at [email protected].

Recent

Integrating JSF, Spring Security and LDAP

Developing Web Services by using Mule, CXF, and SpringDeveloping Web Services by Using Metro Webservices Framework

Developing CXF WS-Security with Spring & Acegi Security

Developing CXF WS-Security with SAMLDeveloping CXF WS-Security with Signature(Certificates)

Developing CXF Web services with WS-Security

RESTful web services using the Jersey frameworkDeveloping Web Services By Using Spring and CXF

Developing Web Services by Using Spring and XFire

Developing Web services Using Spring FrameworkDeveloping Simple Web Services by Using JWSDP

Links

WordPress.com

WordPress.org

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

66 of 67 6/22/2011 2:07 PM

Page 67: (Developing CXF WS-Security With SAML _253 Peter Arockiaraj

Archives

January 2010 (1)

November 2009 (1)

October 2009 (1)September 2009 (9)

Categories

Java

Web Services

RSS

Entries RSS

Comments RSS

Site info

Peter Arockiaraj

Theme: Andreas04 by Andreas Viklund. Blog at WordPress.com.

Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...

67 of 67 6/22/2011 2:07 PM