You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2013/04/18 19:30:13 UTC

svn commit: r1469483 - in /cxf/branches/wss4j2.0-port/rt/ws/security/src: main/java/org/apache/cxf/ws/security/wss4j/ main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/ test/java/org/apache/cxf/ws/security/wss4j/saml/

Author: coheigea
Date: Thu Apr 18 17:30:12 2013
New Revision: 1469483

URL: http://svn.apache.org/r1469483
Log:
Added some more SAML interop tests

Modified:
    cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
    cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SAMLUtils.java
    cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
    cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AbstractSamlPolicyValidator.java
    cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SamlTokenPolicyValidator.java
    cxf/branches/wss4j2.0-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/DOMToStaxSamlTest.java

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JInterceptor.java Thu Apr 18 17:30:12 2013
@@ -190,6 +190,16 @@ public abstract class AbstractWSS4JInter
         if (certConstraints != null) {
             msg.setContextualProperty(WSHandlerConstants.SIG_SUBJECT_CERT_CONSTRAINTS, certConstraints);
         }
+        
+        // Now set SAML SenderVouches + Holder Of Key requirements
+        boolean validateSAMLSubjectConf = 
+            MessageUtils.getContextualBoolean(
+                msg, SecurityConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, true
+            );
+        msg.setContextualProperty(
+            WSHandlerConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, 
+            Boolean.toString(validateSAMLSubjectConf)
+        );
     }
 
     @Override

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SAMLUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SAMLUtils.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SAMLUtils.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SAMLUtils.java Thu Apr 18 17:30:12 2013
@@ -19,31 +19,13 @@
 
 package org.apache.cxf.ws.security.wss4j;
 
-import java.security.Principal;
-import java.security.PublicKey;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.logging.Logger;
 
 import org.w3c.dom.Element;
 
-import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.message.Message;
-import org.apache.cxf.security.transport.TLSSessionInfo;
-import org.apache.wss4j.common.ext.WSSecurityException;
-import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
-import org.apache.wss4j.common.saml.OpenSAMLUtil;
-import org.apache.wss4j.common.saml.SAMLKeyInfo;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
-import org.apache.wss4j.dom.WSConstants;
-import org.apache.wss4j.dom.WSDataRef;
-import org.apache.wss4j.dom.WSSecurityEngineResult;
-import org.apache.wss4j.dom.util.WSSecurityUtil;
 import org.opensaml.common.SAMLVersion;
 import org.opensaml.xml.XMLObject;
 
@@ -52,8 +34,6 @@ import org.opensaml.xml.XMLObject;
  */
 public final class SAMLUtils {
     
-    private static final Logger LOG = LogUtils.getL7dLogger(SAMLUtils.class);
-    
     private SAMLUtils() {
     }
     
@@ -149,217 +129,4 @@ public final class SAMLUtils {
         return Collections.unmodifiableList(roles);
     }
     
-    public static void validateSAMLResults(
-        List<WSSecurityEngineResult> results,
-        Message message,
-        Element body
-    ) throws WSSecurityException {
-        final List<Integer> samlActions = new ArrayList<Integer>(2);
-        samlActions.add(WSConstants.ST_SIGNED);
-        samlActions.add(WSConstants.ST_UNSIGNED);
-        List<WSSecurityEngineResult> samlResults = 
-            WSSecurityUtil.fetchAllActionResults(results, samlActions);
-        
-        if (samlResults.isEmpty()) {
-            return;
-        }
-        
-        final List<Integer> signedActions = new ArrayList<Integer>(2);
-        signedActions.add(WSConstants.SIGN);
-        signedActions.add(WSConstants.UT_SIGN);
-        List<WSSecurityEngineResult> signedResults = 
-            WSSecurityUtil.fetchAllActionResults(results, signedActions);
-        
-        for (WSSecurityEngineResult samlResult : samlResults) {
-            SamlAssertionWrapper assertionWrapper = 
-                (SamlAssertionWrapper)samlResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
-            
-            TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
-            Certificate[] tlsCerts = null;
-            if (tlsInfo != null) {
-                tlsCerts = tlsInfo.getPeerCertificates();
-            }
-            if (!SAMLUtils.checkHolderOfKey(assertionWrapper, signedResults, tlsCerts)) {
-                LOG.warning("Assertion fails holder-of-key requirements");
-                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
-            }
-            if (!SAMLUtils.checkSenderVouches(assertionWrapper, tlsCerts, body, signedResults)) {
-                LOG.warning("Assertion fails sender-vouches requirements");
-                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
-            }
-        }
-        
-    }
-    
-    /**
-     * Check the holder-of-key requirements against the received assertion. The subject
-     * credential of the SAML Assertion must have been used to sign some portion of
-     * the message, thus showing proof-of-possession of the private/secret key. Alternatively,
-     * the subject credential of the SAML Assertion must match a client certificate credential
-     * when 2-way TLS is used.
-     * @param assertionWrapper the SAML Assertion wrapper object
-     * @param signedResults a list of all of the signed results
-     */
-    public static boolean checkHolderOfKey(
-        SamlAssertionWrapper assertionWrapper,
-        List<WSSecurityEngineResult> signedResults,
-        Certificate[] tlsCerts
-    ) {
-        List<String> confirmationMethods = assertionWrapper.getConfirmationMethods();
-        for (String confirmationMethod : confirmationMethods) {
-            if (OpenSAMLUtil.isMethodHolderOfKey(confirmationMethod)) {
-                if (tlsCerts == null && (signedResults == null || signedResults.isEmpty())) {
-                    return false;
-                }
-                SAMLKeyInfo subjectKeyInfo = assertionWrapper.getSubjectKeyInfo();
-                if (!compareCredentials(subjectKeyInfo, signedResults, tlsCerts)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Compare the credentials of the assertion to the credentials used in 2-way TLS or those
-     * used to verify signatures.
-     * Return true on a match
-     * @param subjectKeyInfo the SAMLKeyInfo object
-     * @param signedResults a list of all of the signed results
-     * @return true if the credentials of the assertion were used to verify a signature
-     */
-    public static boolean compareCredentials(
-        SAMLKeyInfo subjectKeyInfo,
-        List<WSSecurityEngineResult> signedResults,
-        Certificate[] tlsCerts
-    ) {
-        X509Certificate[] subjectCerts = subjectKeyInfo.getCerts();
-        PublicKey subjectPublicKey = subjectKeyInfo.getPublicKey();
-        byte[] subjectSecretKey = subjectKeyInfo.getSecret();
-        
-        //
-        // Try to match the TLS certs first
-        //
-        if (tlsCerts != null && tlsCerts.length > 0 && subjectCerts != null 
-            && subjectCerts.length > 0 && tlsCerts[0].equals(subjectCerts[0])) {
-            return true;
-        } else if (tlsCerts != null && tlsCerts.length > 0 && subjectPublicKey != null
-            && tlsCerts[0].getPublicKey().equals(subjectPublicKey)) {
-            return true;
-        }
-        
-        //
-        // Now try the message-level signatures
-        //
-        for (WSSecurityEngineResult signedResult : signedResults) {
-            X509Certificate[] certs =
-                (X509Certificate[])signedResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
-            PublicKey publicKey =
-                (PublicKey)signedResult.get(WSSecurityEngineResult.TAG_PUBLIC_KEY);
-            byte[] secretKey =
-                (byte[])signedResult.get(WSSecurityEngineResult.TAG_SECRET);
-            if (certs != null && certs.length > 0 && subjectCerts != null
-                && subjectCerts.length > 0 && certs[0].equals(subjectCerts[0])) {
-                return true;
-            }
-            if (publicKey != null && publicKey.equals(subjectPublicKey)) {
-                return true;
-            }
-            if (checkSecretKey(secretKey, subjectSecretKey, signedResult)) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    private static boolean checkSecretKey(
-        byte[] secretKey,
-        byte[] subjectSecretKey,
-        WSSecurityEngineResult signedResult
-    ) {
-        if (secretKey != null && subjectSecretKey != null) {
-            if (Arrays.equals(secretKey, subjectSecretKey)) {
-                return true;
-            } else {
-                Principal principal =
-                    (Principal)signedResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
-                if (principal instanceof WSDerivedKeyTokenPrincipal) {
-                    secretKey = ((WSDerivedKeyTokenPrincipal)principal).getSecret();
-                    if (Arrays.equals(secretKey, subjectSecretKey)) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-    
-    /**
-     * Check the sender-vouches requirements against the received assertion. The SAML
-     * Assertion and the SOAP Body must be signed by the same signature.
-     */
-    public static boolean checkSenderVouches(
-        SamlAssertionWrapper assertionWrapper,
-        Certificate[] tlsCerts,
-        Element body,
-        List<WSSecurityEngineResult> signed
-    ) {
-        //
-        // If we have a 2-way TLS connection, then we don't have to check that the
-        // assertion + SOAP body are signed
-        //
-        if (tlsCerts != null && tlsCerts.length > 0) {
-            return true;
-        }
-        List<String> confirmationMethods = assertionWrapper.getConfirmationMethods();
-        for (String confirmationMethod : confirmationMethods) {
-            if (OpenSAMLUtil.isMethodSenderVouches(confirmationMethod)) {
-                if (signed == null || signed.isEmpty()) {
-                    return false;
-                }
-                if (!checkAssertionAndBodyAreSigned(assertionWrapper, body, signed)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Return true if there is a signature which references the Assertion and the SOAP Body.
-     * @param assertionWrapper the SamlAssertionWrapper object
-     * @param body The SOAP body
-     * @param signed The List of signed results
-     * @return true if there is a signature which references the Assertion and the SOAP Body.
-     */
-    private static boolean checkAssertionAndBodyAreSigned(
-        SamlAssertionWrapper assertionWrapper,
-        Element body,
-        List<WSSecurityEngineResult> signed
-    ) {
-        for (WSSecurityEngineResult signedResult : signed) {
-            List<WSDataRef> sl =
-                CastUtils.cast((List<?>)signedResult.get(
-                    WSSecurityEngineResult.TAG_DATA_REF_URIS
-                ));
-            boolean assertionIsSigned = false;
-            boolean bodyIsSigned = false;
-            if (sl != null) {
-                for (WSDataRef dataRef : sl) {
-                    Element se = dataRef.getProtectedElement();
-                    if (se == assertionWrapper.getElement()) {
-                        assertionIsSigned = true;
-                    }
-                    if (se == body) {
-                        bodyIsSigned = true;
-                    }
-                    if (assertionIsSigned && bodyIsSigned) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
 }

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java Thu Apr 18 17:30:12 2013
@@ -20,6 +20,7 @@ package org.apache.cxf.ws.security.wss4j
 
 import java.io.IOException;
 import java.security.Principal;
+import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -65,6 +66,7 @@ import org.apache.cxf.message.MessageUti
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.phase.PhaseInterceptor;
 import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.security.transport.TLSSessionInfo;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.ws.security.SecurityConstants;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
@@ -252,6 +254,12 @@ public class WSS4JInInterceptor extends 
                     msg, SecurityConstants.ENABLE_TIMESTAMP_CACHE, SecurityConstants.TIMESTAMP_CACHE_INSTANCE
                 );
             reqData.setTimestampReplayCache(timestampCache);
+            
+            TLSSessionInfo tlsInfo = msg.get(TLSSessionInfo.class);
+            if (tlsInfo != null) {
+                Certificate[] tlsCerts = tlsInfo.getPeerCertificates();
+                reqData.setTlsCerts(tlsCerts);
+            }
 
             /*
              * Get and check the Signature specific parameters first because
@@ -364,15 +372,6 @@ public class WSS4JInInterceptor extends 
             LOG.warning(warning);
         }
         
-        // Now check SAML SenderVouches + Holder Of Key requirements
-        boolean validateSAMLSubjectConf = 
-            MessageUtils.getContextualBoolean(
-                msg, SecurityConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, true
-            );
-        if (validateSAMLSubjectConf) {
-            SAMLUtils.validateSAMLResults(wsResult, msg, body);
-        }
-        
     }
     
     private void storeSignature(

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AbstractSamlPolicyValidator.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AbstractSamlPolicyValidator.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AbstractSamlPolicyValidator.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/AbstractSamlPolicyValidator.java Thu Apr 18 17:30:12 2013
@@ -24,10 +24,10 @@ import java.util.List;
 
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
-import org.apache.cxf.ws.security.wss4j.SAMLUtils;
 import org.apache.wss4j.common.saml.SAMLKeyInfo;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
 import org.apache.wss4j.dom.WSSecurityEngineResult;
+import org.apache.wss4j.dom.saml.DOMSAMLUtil;
 import org.apache.wss4j.policy.SPConstants.IncludeTokenType;
 import org.apache.wss4j.policy.model.AbstractToken;
 
@@ -77,7 +77,7 @@ public abstract class AbstractSamlPolicy
         List<WSSecurityEngineResult> signedResults,
         Certificate[] tlsCerts
     ) {
-        return SAMLUtils.checkHolderOfKey(assertionWrapper, signedResults, tlsCerts);
+        return DOMSAMLUtil.checkHolderOfKey(assertionWrapper, signedResults, tlsCerts);
     }
 
     /**
@@ -93,7 +93,7 @@ public abstract class AbstractSamlPolicy
         List<WSSecurityEngineResult> signedResults,
         Certificate[] tlsCerts
     ) {
-        return SAMLUtils.compareCredentials(subjectKeyInfo, signedResults, tlsCerts);
+        return DOMSAMLUtil.compareCredentials(subjectKeyInfo, signedResults, tlsCerts);
     }
     
 }

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SamlTokenPolicyValidator.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SamlTokenPolicyValidator.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SamlTokenPolicyValidator.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyvalidators/SamlTokenPolicyValidator.java Thu Apr 18 17:30:12 2013
@@ -32,10 +32,10 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.security.transport.TLSSessionInfo;
 import org.apache.cxf.ws.policy.AssertionInfo;
 import org.apache.cxf.ws.policy.AssertionInfoMap;
-import org.apache.cxf.ws.security.wss4j.SAMLUtils;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.WSSecurityEngineResult;
+import org.apache.wss4j.dom.saml.DOMSAMLUtil;
 import org.apache.wss4j.dom.util.WSSecurityUtil;
 import org.apache.wss4j.policy.SPConstants;
 import org.apache.wss4j.policy.model.SamlToken;
@@ -118,7 +118,7 @@ public class SamlTokenPolicyValidator ex
                     ai.setNotAsserted("Assertion fails holder-of-key requirements");
                     continue;
                 }
-                if (!SAMLUtils.checkSenderVouches(assertionWrapper, tlsCerts, body, signed)) {
+                if (!DOMSAMLUtil.checkSenderVouches(assertionWrapper, tlsCerts, body, signed)) {
                     ai.setNotAsserted("Assertion fails sender-vouches requirements");
                     continue;
                 }

Modified: cxf/branches/wss4j2.0-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/DOMToStaxSamlTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/DOMToStaxSamlTest.java?rev=1469483&r1=1469482&r2=1469483&view=diff
==============================================================================
--- cxf/branches/wss4j2.0-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/DOMToStaxSamlTest.java (original)
+++ cxf/branches/wss4j2.0-port/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/saml/DOMToStaxSamlTest.java Thu Apr 18 17:30:12 2013
@@ -45,7 +45,6 @@ import org.junit.Test;
 /**
  * In these test-cases, the client is using DOM and the service is using StaX.
  */
-@org.junit.Ignore
 public class DOMToStaxSamlTest extends AbstractSecurityTest {
     
     @Test
@@ -54,7 +53,35 @@ public class DOMToStaxSamlTest extends A
         Service service = createService();
         
         WSSSecurityProperties inProperties = new WSSSecurityProperties();
-        // inProperties.setCallbackHandler(new TestPwdCallback());
+        inProperties.setValidateSamlSubjectConfirmation(false);
+        WSS4JStaxInInterceptor inhandler = new WSS4JStaxInInterceptor(inProperties);
+        service.getInInterceptors().add(inhandler);
+        
+        // Create + configure client
+        Echo echo = createClientProxy();
+        
+        Client client = ClientProxy.getClient(echo);
+        client.getInInterceptors().add(new LoggingInInterceptor());
+        client.getOutInterceptors().add(new LoggingOutInterceptor());
+        
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.SAML_TOKEN_UNSIGNED);
+        properties.put(
+            WSHandlerConstants.SAML_CALLBACK_REF, new SAML1CallbackHandler()
+        );
+        
+        WSS4JOutInterceptor ohandler = new WSS4JOutInterceptor(properties);
+        client.getOutInterceptors().add(ohandler);
+
+        assertEquals("test", echo.echo("test"));
+    }
+    
+    @Test
+    public void testSaml1SignedSenderVouches() throws Exception {
+        // Create + configure service
+        Service service = createService();
+        
+        WSSSecurityProperties inProperties = new WSSSecurityProperties();
         Properties cryptoProperties = 
             CryptoFactory.getProperties("insecurity.properties", this.getClass().getClassLoader());
         inProperties.setSignatureVerificationCryptoProperties(cryptoProperties);
@@ -69,10 +96,80 @@ public class DOMToStaxSamlTest extends A
         client.getOutInterceptors().add(new LoggingOutInterceptor());
         
         Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.SAML_TOKEN_SIGNED);
+        properties.put(
+            WSHandlerConstants.SAML_CALLBACK_CLASS, 
+            "org.apache.cxf.ws.security.wss4j.saml.SAML1CallbackHandler"
+        );
+        properties.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+        properties.put(WSHandlerConstants.USER, "alice");
+        properties.put(WSHandlerConstants.PW_CALLBACK_REF, new PasswordCallbackHandler());
+        properties.put(WSHandlerConstants.SIG_PROP_FILE, "alice.properties");
+        
+        WSS4JOutInterceptor ohandler = new WSS4JOutInterceptor(properties);
+        client.getOutInterceptors().add(ohandler);
+
+        assertEquals("test", echo.echo("test"));
+    }
+    
+    @Test
+    public void testSaml2() throws Exception {
+        // Create + configure service
+        Service service = createService();
+        
+        WSSSecurityProperties inProperties = new WSSSecurityProperties();
+        inProperties.setValidateSamlSubjectConfirmation(false);
+        WSS4JStaxInInterceptor inhandler = new WSS4JStaxInInterceptor(inProperties);
+        service.getInInterceptors().add(inhandler);
+        
+        // Create + configure client
+        Echo echo = createClientProxy();
+        
+        Client client = ClientProxy.getClient(echo);
+        client.getInInterceptors().add(new LoggingInInterceptor());
+        client.getOutInterceptors().add(new LoggingOutInterceptor());
+        
+        Map<String, Object> properties = new HashMap<String, Object>();
         properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.SAML_TOKEN_UNSIGNED);
         properties.put(
-            WSHandlerConstants.SAML_CALLBACK_REF, new SAML1CallbackHandler()
+            WSHandlerConstants.SAML_CALLBACK_REF, new SAML2CallbackHandler()
+        );
+        
+        WSS4JOutInterceptor ohandler = new WSS4JOutInterceptor(properties);
+        client.getOutInterceptors().add(ohandler);
+
+        assertEquals("test", echo.echo("test"));
+    }
+    
+    @Test
+    public void testSaml2SignedSenderVouches() throws Exception {
+        // Create + configure service
+        Service service = createService();
+        
+        WSSSecurityProperties inProperties = new WSSSecurityProperties();
+        Properties cryptoProperties = 
+            CryptoFactory.getProperties("insecurity.properties", this.getClass().getClassLoader());
+        inProperties.setSignatureVerificationCryptoProperties(cryptoProperties);
+        WSS4JStaxInInterceptor inhandler = new WSS4JStaxInInterceptor(inProperties);
+        service.getInInterceptors().add(inhandler);
+        
+        // Create + configure client
+        Echo echo = createClientProxy();
+        
+        Client client = ClientProxy.getClient(echo);
+        client.getInInterceptors().add(new LoggingInInterceptor());
+        client.getOutInterceptors().add(new LoggingOutInterceptor());
+        
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.SAML_TOKEN_SIGNED);
+        properties.put(
+            WSHandlerConstants.SAML_CALLBACK_CLASS, 
+            "org.apache.cxf.ws.security.wss4j.saml.SAML2CallbackHandler"
         );
+        properties.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+        properties.put(WSHandlerConstants.USER, "alice");
+        properties.put(WSHandlerConstants.PW_CALLBACK_REF, new PasswordCallbackHandler());
+        properties.put(WSHandlerConstants.SIG_PROP_FILE, "alice.properties");
         
         WSS4JOutInterceptor ohandler = new WSS4JOutInterceptor(properties);
         client.getOutInterceptors().add(ohandler);