You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2011/05/31 15:50:14 UTC

svn commit: r1129673 - in /webservices/wss4j/trunk/src: main/java/org/apache/ws/security/ main/java/org/apache/ws/security/processor/ main/java/org/apache/ws/security/str/ test/java/org/apache/ws/security/misc/

Author: coheigea
Date: Tue May 31 13:50:14 2011
New Revision: 1129673

URL: http://svn.apache.org/viewvc?rev=1129673&view=rev
Log:
[WSS-290] - Create Principals when processing SAML and BinarySecurityTokens

Added:
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/SAMLTokenPrincipal.java
    webservices/wss4j/trunk/src/test/java/org/apache/ws/security/misc/PrincipalTest.java
Modified:
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/WSSecurityEngineResult.java
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/str/SignatureSTRParser.java

Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/SAMLTokenPrincipal.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/SAMLTokenPrincipal.java?rev=1129673&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/SAMLTokenPrincipal.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/SAMLTokenPrincipal.java Tue May 31 13:50:14 2011
@@ -0,0 +1,85 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ws.security;
+
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.opensaml.common.SAMLVersion;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * A principal that represents a SAML Token. It parses the Subject and returns the Subject 
+ * name value as the Principal name.
+ */
+public class SAMLTokenPrincipal implements Principal, Serializable {
+
+    private String name;
+    private AssertionWrapper assertion;
+    
+    public SAMLTokenPrincipal(AssertionWrapper assertion) {
+        this.assertion = assertion;
+        if (assertion.getSamlVersion() == SAMLVersion.VERSION_20) {
+            org.opensaml.saml2.core.Subject subject = assertion.getSaml2().getSubject();
+            if (subject != null && subject.getNameID() != null) {
+                name = subject.getNameID().getValue();
+            }
+        } else {
+            org.opensaml.saml1.core.Subject samlSubject = null;
+            for (org.opensaml.saml1.core.Statement stmt : assertion.getSaml1().getStatements()) {
+                if (stmt instanceof org.opensaml.saml1.core.AttributeStatement) {
+                    org.opensaml.saml1.core.AttributeStatement attrStmt = 
+                        (org.opensaml.saml1.core.AttributeStatement) stmt;
+                    samlSubject = attrStmt.getSubject();
+                } else if (stmt instanceof org.opensaml.saml1.core.AuthenticationStatement) {
+                    org.opensaml.saml1.core.AuthenticationStatement authStmt = 
+                        (org.opensaml.saml1.core.AuthenticationStatement) stmt;
+                    samlSubject = authStmt.getSubject();
+                } else {
+                    org.opensaml.saml1.core.AuthorizationDecisionStatement authzStmt =
+                        (org.opensaml.saml1.core.AuthorizationDecisionStatement)stmt;
+                    samlSubject = authzStmt.getSubject();
+                }
+                if (samlSubject != null) {
+                    break;
+                }
+            }
+            if (samlSubject != null && samlSubject.getNameIdentifier() != null) {
+                name = samlSubject.getNameIdentifier().getNameIdentifier();
+            }
+        }
+    }
+    
+    public AssertionWrapper getToken() {
+        return assertion;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getId() {
+        if (assertion != null) {
+            return assertion.getId();
+        }
+        return null;
+    }
+    
+}

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/WSSecurityEngineResult.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/WSSecurityEngineResult.java?rev=1129673&r1=1129672&r2=1129673&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/WSSecurityEngineResult.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/WSSecurityEngineResult.java Tue May 31 13:50:14 2011
@@ -174,7 +174,7 @@ public class WSSecurityEngineResult exte
      * The value under this tag is of type java.security.Principal.
      */
     public static final String TAG_PRINCIPAL = "principal";
-
+    
     /**
      * Tag denoting references to a List of Data ref URIs.
      *
@@ -300,6 +300,10 @@ public class WSSecurityEngineResult exte
         put(TAG_VALIDATED_TOKEN, Boolean.FALSE);
     }
     
+    public WSSecurityEngineResult(int act, UsernameToken usernameToken) {
+        this(act, usernameToken, null);
+    }
+    
     public WSSecurityEngineResult(int act, UsernameToken usernameToken, Principal principal) {
         put(TAG_ACTION, new Integer(act));
         put(TAG_USERNAME_TOKEN, usernameToken);

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java?rev=1129673&r1=1129672&r2=1129673&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java Tue May 31 13:50:14 2011
@@ -19,6 +19,7 @@
 
 package org.apache.ws.security.processor;
 
+import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDocInfo;
 import org.apache.ws.security.WSSConfig;
@@ -75,14 +76,19 @@ public class BinarySecurityTokenProcesso
             credential.setCertificates(certs);
             
             Credential returnedCredential = validator.validate(credential, data);
+            result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
             
             if (returnedCredential.getTransformedToken() != null) {
                 result.put(
                     WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, 
                     returnedCredential.getTransformedToken()
                 );
+                SAMLTokenPrincipal samlPrincipal = 
+                    new SAMLTokenPrincipal(credential.getTransformedToken());
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, samlPrincipal);
+            } else if (certs != null && certs[0] != null) {
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, certs[0].getSubjectX500Principal());
             }
-            result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
         }
         
         wsDocInfo.addResult(result);

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java?rev=1129673&r1=1129672&r2=1129673&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java Tue May 31 13:50:14 2011
@@ -19,6 +19,7 @@
 
 package org.apache.ws.security.processor;
 
+import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDocInfo;
 import org.apache.ws.security.WSSecurityEngineResult;
@@ -63,15 +64,21 @@ public class SAMLTokenProcessor implemen
         } else {
             result = new WSSecurityEngineResult(WSConstants.ST_UNSIGNED, assertion);
         }
-        String id = assertion.getId();
-        result.put(WSSecurityEngineResult.TAG_ID, id);
-        if (credential.getTransformedToken() != null) {
-            result.put(
-                WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, credential.getTransformedToken()
-            );
-        }
+        
+        result.put(WSSecurityEngineResult.TAG_ID, assertion.getId());
+
         if (validator != null) {
             result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
+            if (credential.getTransformedToken() != null) {
+                result.put(
+                    WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, credential.getTransformedToken()
+                );
+                SAMLTokenPrincipal samlPrincipal = 
+                    new SAMLTokenPrincipal(credential.getTransformedToken());
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, samlPrincipal);
+            } else {
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, new SAMLTokenPrincipal(assertion));
+            }
         }
         wsDocInfo.addResult(result);
         return java.util.Collections.singletonList(result);

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java?rev=1129673&r1=1129672&r2=1129673&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java Tue May 31 13:50:14 2011
@@ -19,6 +19,7 @@
 
 package org.apache.ws.security.processor;
 
+import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDocInfo;
 import org.apache.ws.security.WSSConfig;
@@ -51,29 +52,33 @@ public class UsernameTokenProcessor impl
         Credential credential = handleUsernameToken(elem, validator, data);
         UsernameToken token = credential.getUsernametoken();
         
-        WSUsernameTokenPrincipal principal = 
-            new WSUsernameTokenPrincipal(token.getName(), token.isHashed());
-        principal.setNonce(token.getNonce());
-        principal.setPassword(token.getPassword());
-        principal.setCreatedTime(token.getCreated());
-        principal.setPasswordType(token.getPasswordType());
-        
         int action = WSConstants.UT;
         if (token.getPassword() == null) { 
             action = WSConstants.UT_NOPASSWORD;
         }
-        WSSecurityEngineResult result = 
-            new WSSecurityEngineResult(action, token, principal);
+        WSSecurityEngineResult result = new WSSecurityEngineResult(action, token);
         result.put(WSSecurityEngineResult.TAG_ID, token.getID());
-        if (credential.getTransformedToken() != null) {
-            result.put(
-                WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, credential.getTransformedToken()
-            );
-        }
         
         if (validator != null) {
             result.put(WSSecurityEngineResult.TAG_VALIDATED_TOKEN, Boolean.TRUE);
+            if (credential.getTransformedToken() != null) {
+                result.put(
+                    WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN, credential.getTransformedToken()
+                );
+                SAMLTokenPrincipal samlPrincipal = 
+                    new SAMLTokenPrincipal(credential.getTransformedToken());
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, samlPrincipal);
+            } else {
+                WSUsernameTokenPrincipal principal = 
+                    new WSUsernameTokenPrincipal(token.getName(), token.isHashed());
+                principal.setNonce(token.getNonce());
+                principal.setPassword(token.getPassword());
+                principal.setCreatedTime(token.getCreated());
+                principal.setPasswordType(token.getPasswordType());
+                result.put(WSSecurityEngineResult.TAG_PRINCIPAL, principal);
+            }
         }
+        
         wsDocInfo.addTokenElement(elem);
         wsDocInfo.addResult(result);
         return java.util.Collections.singletonList(result);

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/str/SignatureSTRParser.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/str/SignatureSTRParser.java?rev=1129673&r1=1129672&r2=1129673&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/str/SignatureSTRParser.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/str/SignatureSTRParser.java Tue May 31 13:50:14 2011
@@ -20,6 +20,7 @@
 package org.apache.ws.security.str;
 
 import org.apache.ws.security.CustomTokenPrincipal;
+import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDerivedKeyTokenPrincipal;
 import org.apache.ws.security.WSDocInfo;
@@ -337,8 +338,7 @@ public class SignatureSTRParser implemen
     private Principal createPrincipalFromSAML(
         AssertionWrapper assertion
     ) {
-        Principal principal = new CustomTokenPrincipal(assertion.getId());
-        ((CustomTokenPrincipal)principal).setTokenObject(assertion);
+        SAMLTokenPrincipal principal = new SAMLTokenPrincipal(assertion);
         String confirmMethod = null;
         List<String> methods = assertion.getConfirmationMethods();
         if (methods != null && methods.size() > 0) {

Added: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/misc/PrincipalTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/misc/PrincipalTest.java?rev=1129673&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/misc/PrincipalTest.java (added)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/misc/PrincipalTest.java Tue May 31 13:50:14 2011
@@ -0,0 +1,340 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ws.security.misc;
+
+import org.apache.ws.security.SAMLTokenPrincipal;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.common.SAML1CallbackHandler;
+import org.apache.ws.security.common.SAML2CallbackHandler;
+import org.apache.ws.security.common.UsernamePasswordCallbackHandler;
+import org.apache.ws.security.common.SOAPUtil;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.components.crypto.CryptoType;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSAMLToken;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.saml.ext.SAMLParms;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.Validator;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * Test various principal objects after processing a security token.
+ */
+public class PrincipalTest extends org.junit.Assert {
+    private static final org.apache.commons.logging.Log LOG = 
+        org.apache.commons.logging.LogFactory.getLog(PrincipalTest.class);
+    
+    private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
+
+    /**
+     * Test the principal that is created after processing a Username Token
+     */
+    @org.junit.Test
+    public void testUsernameToken() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("wernerd", "verySecret");
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+            LOG.debug(outputString);
+        }
+        List<WSSecurityEngineResult> results = verify(signedDoc, null);
+        
+        Principal principal = (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof WSUsernameTokenPrincipal;
+        assert "wernerd".equals(principal.getName());
+        WSUsernameTokenPrincipal userPrincipal = (WSUsernameTokenPrincipal)principal;
+        assert userPrincipal.getCreatedTime() != null;
+        assert userPrincipal.getNonce() != null;
+        assert userPrincipal.getPassword() != null;
+        assert userPrincipal.isPasswordDigest();
+        assert WSConstants.PASSWORD_DIGEST.equals(userPrincipal.getPasswordType());
+    }
+    
+    /**
+     * Test the principal that is created after processing a Username Token, which has been
+     * transformed into a SAML Assertion.
+     */
+    @org.junit.Test
+    public void testTransformedUsernameToken() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("wernerd", "verySecret");
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+            LOG.debug(outputString);
+        }
+        List<WSSecurityEngineResult> results = 
+            verify(signedDoc, new DummyValidator(), WSSecurityEngine.USERNAME_TOKEN, null);
+        
+        Principal principal = (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof SAMLTokenPrincipal;
+        assert principal.getName().contains("uid=joe");
+        assert ((SAMLTokenPrincipal)principal).getToken() != null;
+    }
+    
+    /**
+     * Test the principal that is created after processing a SAML Token
+     */
+    @org.junit.Test
+    public void testSAMLToken() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+            LOG.debug(outputString);
+        }
+        
+        List<WSSecurityEngineResult> results = verify(unsignedDoc, null);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+        AssertionWrapper receivedAssertion = 
+            (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+        assertTrue(receivedAssertion != null);
+        
+        Principal principal = 
+            (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof SAMLTokenPrincipal;
+        assert principal.getName().contains("uid=joe");
+        assert ((SAMLTokenPrincipal)principal).getToken() != null;
+    }
+    
+    /**
+     * Test the principal that is created after processing a SAML2 Token
+     */
+    @org.junit.Test
+    public void testSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+            LOG.debug(outputString);
+        }
+        
+        List<WSSecurityEngineResult> results = verify(unsignedDoc, null);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+        AssertionWrapper receivedAssertion = 
+            (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+        assertTrue(receivedAssertion != null);
+        
+        Principal principal = 
+            (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof SAMLTokenPrincipal;
+        assert principal.getName().contains("uid=joe");
+        assert ((SAMLTokenPrincipal)principal).getToken() != null;
+    }
+    
+    /**
+     * Test the principal that is created after processing a SAML Token, which has been
+     * transformed into another SAML Token.
+     */
+    @org.junit.Test
+    public void testTransformedSAMLToken() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("www.example.com");
+        
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertion = new AssertionWrapper(samlParms);
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+            LOG.debug(outputString);
+        }
+        
+        List<WSSecurityEngineResult> results = 
+            verify(unsignedDoc, new DummyValidator(), WSSecurityEngine.SAML_TOKEN, null);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+        AssertionWrapper receivedAssertion = 
+            (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+        assertTrue(receivedAssertion != null);
+        
+        Principal principal = 
+            (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof SAMLTokenPrincipal;
+        assert principal.getName().contains("uid=joe");
+        assert ((SAMLTokenPrincipal)principal).getToken() != null;
+    }
+    
+    /**
+     * Test the principal that is created after processing (and explicitly validating)
+     * a BinarySecurityToken.
+     */
+    @org.junit.Test
+    public void testBinarySecurityToken() throws Exception {
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        X509Security bst = new X509Security(doc);
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+        cryptoType.setAlias("wss40");
+        Crypto crypto = CryptoFactory.getInstance("wss40.properties");
+        X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+        bst.setX509Certificate(certs[0]);
+        
+        WSSecurityUtil.prependChildElement(secHeader.getSecurityHeader(), bst.getElement());
+        
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+            LOG.debug(outputString);
+        }
+        
+        List<WSSecurityEngineResult> results = 
+            verify(doc, new DummyValidator(), WSSecurityEngine.BINARY_TOKEN, crypto);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.BST);
+        BinarySecurity token =
+            (BinarySecurity)actionResult.get(WSSecurityEngineResult.TAG_BINARY_SECURITY_TOKEN);
+        assert token != null;
+        
+        Principal principal = 
+            (Principal)results.get(0).get(WSSecurityEngineResult.TAG_PRINCIPAL);
+        assert principal instanceof SAMLTokenPrincipal;
+        assert principal.getName().contains("uid=joe");
+        assert ((SAMLTokenPrincipal)principal).getToken() != null;
+    }
+    
+    /**
+     * Verifies the soap envelope
+     */
+    private List<WSSecurityEngineResult> verify(
+        Document doc,
+        Crypto crypto
+    ) throws Exception {
+        return verify(doc, null, null, crypto);
+    }
+    
+    /**
+     * Verifies the soap envelope
+     */
+    private List<WSSecurityEngineResult> verify(
+        Document doc, 
+        Validator validator,
+        QName validatorName,
+        Crypto crypto
+    ) throws Exception {
+        WSSConfig config = WSSConfig.getNewInstance();
+        WSSecurityEngine secEngine = new WSSecurityEngine();
+        secEngine.setWssConfig(config);
+        if (validator != null && validatorName != null) {
+            config.setValidator(validatorName, validator);
+        }
+        return secEngine.processSecurityHeader(doc, null, callbackHandler, crypto);
+    }
+    
+    /**
+     * A Dummy Validator instance that just creates a new SAML Assertion, ignoring the
+     * credential it has been passed.
+     */
+    private static class DummyValidator implements Validator {
+
+        public Credential validate(Credential credential, RequestData data) throws WSSecurityException {
+            try {
+                SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+                callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
+                callbackHandler.setIssuer("www.example.com");
+                
+                SAMLParms samlParms = new SAMLParms();
+                samlParms.setCallbackHandler(callbackHandler);
+                AssertionWrapper assertion = new AssertionWrapper(samlParms);
+    
+                credential.setTransformedToken(assertion);
+                return credential;
+            } catch (Exception ex) {
+                throw new WSSecurityException(WSSecurityException.FAILURE);
+            }
+        }
+        
+    }
+}