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/11/01 15:46:06 UTC

svn commit: r1196030 - in /webservices/wss4j/trunk/src: main/java/org/apache/ws/security/saml/ext/ test/java/org/apache/ws/security/common/ test/java/org/apache/ws/security/saml/

Author: coheigea
Date: Tue Nov  1 14:46:06 2011
New Revision: 1196030

URL: http://svn.apache.org/viewvc?rev=1196030&view=rev
Log:
[WSS-322] - Add the ability to set DOM Elements directly on a SAMLCallback object

Added:
    webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/SAMLElementCallbackHandler.java
Modified:
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
    webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/SAMLCallback.java
    webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenTest.java

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java?rev=1196030&r1=1196029&r2=1196030&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java Tue Nov  1 14:46:06 2011
@@ -149,21 +149,7 @@ public class AssertionWrapper {
     public AssertionWrapper(Element element) throws WSSecurityException {
         OpenSAMLUtil.initSamlEngine();
         
-        this.xmlObject = OpenSAMLUtil.fromDom(element);
-        if (xmlObject instanceof org.opensaml.saml1.core.Assertion) {
-            this.saml1 = (org.opensaml.saml1.core.Assertion) xmlObject;
-            samlVersion = SAMLVersion.VERSION_11;
-        } else if (xmlObject instanceof org.opensaml.saml2.core.Assertion) {
-            this.saml2 = (org.opensaml.saml2.core.Assertion) xmlObject;
-            samlVersion = SAMLVersion.VERSION_20;
-        } else {
-            log.error(
-                "AssertionWrapper: found unexpected type " 
-                + (xmlObject != null ? xmlObject.getClass().getName() : xmlObject)
-            );
-        }
-        
-        assertionElement = element;
+        parseElement(element);
     }
 
     /**
@@ -214,7 +200,6 @@ public class AssertionWrapper {
      * Constructor AssertionWrapper creates a new AssertionWrapper instance.
      * This constructor is primarily called on the client side to initialize
      * the wrapper from a configuration file. <br>
-     * NOTE: The OpenSaml library MUST be initialized prior to constructing an AssertionWrapper
      *
      * @param parms of type SAMLParms
      */
@@ -244,99 +229,13 @@ public class AssertionWrapper {
                 "UnsupportedCallbackException while creating SAML assertion wrapper", e
             );
         }
-
-        samlVersion = samlCallbacks[0].getSamlVersion();
-        if (samlVersion == null) {
-            samlVersion = parms.getSAMLVersion();
-        }
-        String issuer = samlCallbacks[0].getIssuer();
-        if (issuer == null && parms.getIssuer() != null) {
-            issuer = parms.getIssuer();
-        }
-        if (samlVersion.equals(SAMLVersion.VERSION_11)) {
-            // Build a SAML v1.1 assertion
-            saml1 = SAML1ComponentBuilder.createSamlv1Assertion(issuer);
-
-            try {
-                // Process the SAML authentication statement(s)
-                List<AuthenticationStatement> authenticationStatements = 
-                    SAML1ComponentBuilder.createSamlv1AuthenticationStatement(
-                        samlCallbacks[0].getAuthenticationStatementData()
-                    );
-                saml1.getAuthenticationStatements().addAll(authenticationStatements);
-    
-                // Process the SAML attribute statement(s)            
-                List<AttributeStatement> attributeStatements =
-                        SAML1ComponentBuilder.createSamlv1AttributeStatement(
-                            samlCallbacks[0].getAttributeStatementData()
-                        );
-                saml1.getAttributeStatements().addAll(attributeStatements);
-    
-                // Process the SAML authorization decision statement(s)
-                List<AuthorizationDecisionStatement> authDecisionStatements =
-                        SAML1ComponentBuilder.createSamlv1AuthorizationDecisionStatement(
-                            samlCallbacks[0].getAuthDecisionStatementData()
-                        );
-                saml1.getAuthorizationDecisionStatements().addAll(authDecisionStatements);
-    
-                // Build the complete assertion
-                org.opensaml.saml1.core.Conditions conditions = 
-                    SAML1ComponentBuilder.createSamlv1Conditions(samlCallbacks[0].getConditions());
-                saml1.setConditions(conditions);
-            } catch (org.opensaml.xml.security.SecurityException ex) {
-                throw new WSSecurityException(
-                    "Error generating KeyInfo from signing credential", ex
-                );
-            }
-
-            // Set the OpenSaml2 XMLObject instance
-            xmlObject = saml1;
-
-        } else if (samlVersion.equals(SAMLVersion.VERSION_20)) {
-            // Build a SAML v2.0 assertion
-            saml2 = SAML2ComponentBuilder.createAssertion();
-            Issuer samlIssuer = SAML2ComponentBuilder.createIssuer(issuer);
-
-            // Authn Statement(s)
-            List<AuthnStatement> authnStatements = 
-                SAML2ComponentBuilder.createAuthnStatement(
-                    samlCallbacks[0].getAuthenticationStatementData()
-                );
-            saml2.getAuthnStatements().addAll(authnStatements);
-
-            // Attribute statement(s)
-            List<org.opensaml.saml2.core.AttributeStatement> attributeStatements = 
-                SAML2ComponentBuilder.createAttributeStatement(
-                    samlCallbacks[0].getAttributeStatementData()
-                );
-            saml2.getAttributeStatements().addAll(attributeStatements);
-
-            // AuthzDecisionStatement(s)
-            List<AuthzDecisionStatement> authDecisionStatements =
-                    SAML2ComponentBuilder.createAuthorizationDecisionStatement(
-                        samlCallbacks[0].getAuthDecisionStatementData()
-                    );
-            saml2.getAuthzDecisionStatements().addAll(authDecisionStatements);
-
-            // Build the SAML v2.0 assertion
-            saml2.setIssuer(samlIssuer);
-            
-            try {
-                org.opensaml.saml2.core.Subject subject = 
-                    SAML2ComponentBuilder.createSaml2Subject(samlCallbacks[0].getSubject());
-                saml2.setSubject(subject);
-            } catch (org.opensaml.xml.security.SecurityException ex) {
-                throw new WSSecurityException(
-                    "Error generating KeyInfo from signing credential", ex
-                );
-            }
-            
-            org.opensaml.saml2.core.Conditions conditions = 
-                SAML2ComponentBuilder.createConditions(samlCallbacks[0].getConditions());
-            saml2.setConditions(conditions);
-
-            // Set the OpenSaml2 XMLObject instance
-            xmlObject = saml2;
+        
+        // See if we already have a DOM element in SAMLCallback
+        if (samlCallbacks[0].getAssertionElement() != null) {
+            parseElement(samlCallbacks[0].getAssertionElement());
+        } else {
+            // If not then parse the SAMLCallback object
+            parseCallback(samlCallbacks[0], parms);
         }
     }
 
@@ -771,5 +670,127 @@ public class AssertionWrapper {
         }
         return null;
     }
+    
+    /**
+     * Parse the DOM Element into Opensaml objects.
+     */
+    private void parseElement(Element element) throws WSSecurityException {
+        this.xmlObject = OpenSAMLUtil.fromDom(element);
+        if (xmlObject instanceof org.opensaml.saml1.core.Assertion) {
+            this.saml1 = (org.opensaml.saml1.core.Assertion) xmlObject;
+            samlVersion = SAMLVersion.VERSION_11;
+        } else if (xmlObject instanceof org.opensaml.saml2.core.Assertion) {
+            this.saml2 = (org.opensaml.saml2.core.Assertion) xmlObject;
+            samlVersion = SAMLVersion.VERSION_20;
+        } else {
+            log.error(
+                "AssertionWrapper: found unexpected type " 
+                + (xmlObject != null ? xmlObject.getClass().getName() : xmlObject)
+            );
+        }
+        
+        assertionElement = element;
+    }
+    
+    /**
+     * Parse a SAMLCallback object to create a SAML Assertion
+     */
+    private void parseCallback(
+        SAMLCallback samlCallback, SAMLParms parms
+    ) throws WSSecurityException {
+        samlVersion = samlCallback.getSamlVersion();
+        if (samlVersion == null) {
+            samlVersion = parms.getSAMLVersion();
+        }
+        String issuer = samlCallback.getIssuer();
+        if (issuer == null && parms.getIssuer() != null) {
+            issuer = parms.getIssuer();
+        }
+        if (samlVersion.equals(SAMLVersion.VERSION_11)) {
+            // Build a SAML v1.1 assertion
+            saml1 = SAML1ComponentBuilder.createSamlv1Assertion(issuer);
+
+            try {
+                // Process the SAML authentication statement(s)
+                List<AuthenticationStatement> authenticationStatements = 
+                    SAML1ComponentBuilder.createSamlv1AuthenticationStatement(
+                        samlCallback.getAuthenticationStatementData()
+                    );
+                saml1.getAuthenticationStatements().addAll(authenticationStatements);
+    
+                // Process the SAML attribute statement(s)            
+                List<AttributeStatement> attributeStatements =
+                        SAML1ComponentBuilder.createSamlv1AttributeStatement(
+                            samlCallback.getAttributeStatementData()
+                        );
+                saml1.getAttributeStatements().addAll(attributeStatements);
+    
+                // Process the SAML authorization decision statement(s)
+                List<AuthorizationDecisionStatement> authDecisionStatements =
+                        SAML1ComponentBuilder.createSamlv1AuthorizationDecisionStatement(
+                            samlCallback.getAuthDecisionStatementData()
+                        );
+                saml1.getAuthorizationDecisionStatements().addAll(authDecisionStatements);
+    
+                // Build the complete assertion
+                org.opensaml.saml1.core.Conditions conditions = 
+                    SAML1ComponentBuilder.createSamlv1Conditions(samlCallback.getConditions());
+                saml1.setConditions(conditions);
+            } catch (org.opensaml.xml.security.SecurityException ex) {
+                throw new WSSecurityException(
+                    "Error generating KeyInfo from signing credential", ex
+                );
+            }
+
+            // Set the OpenSaml2 XMLObject instance
+            xmlObject = saml1;
+
+        } else if (samlVersion.equals(SAMLVersion.VERSION_20)) {
+            // Build a SAML v2.0 assertion
+            saml2 = SAML2ComponentBuilder.createAssertion();
+            Issuer samlIssuer = SAML2ComponentBuilder.createIssuer(issuer);
+
+            // Authn Statement(s)
+            List<AuthnStatement> authnStatements = 
+                SAML2ComponentBuilder.createAuthnStatement(
+                    samlCallback.getAuthenticationStatementData()
+                );
+            saml2.getAuthnStatements().addAll(authnStatements);
+
+            // Attribute statement(s)
+            List<org.opensaml.saml2.core.AttributeStatement> attributeStatements = 
+                SAML2ComponentBuilder.createAttributeStatement(
+                    samlCallback.getAttributeStatementData()
+                );
+            saml2.getAttributeStatements().addAll(attributeStatements);
+
+            // AuthzDecisionStatement(s)
+            List<AuthzDecisionStatement> authDecisionStatements =
+                    SAML2ComponentBuilder.createAuthorizationDecisionStatement(
+                        samlCallback.getAuthDecisionStatementData()
+                    );
+            saml2.getAuthzDecisionStatements().addAll(authDecisionStatements);
+
+            // Build the SAML v2.0 assertion
+            saml2.setIssuer(samlIssuer);
+            
+            try {
+                org.opensaml.saml2.core.Subject subject = 
+                    SAML2ComponentBuilder.createSaml2Subject(samlCallback.getSubject());
+                saml2.setSubject(subject);
+            } catch (org.opensaml.xml.security.SecurityException ex) {
+                throw new WSSecurityException(
+                    "Error generating KeyInfo from signing credential", ex
+                );
+            }
+            
+            org.opensaml.saml2.core.Conditions conditions = 
+                SAML2ComponentBuilder.createConditions(samlCallback.getConditions());
+            saml2.setConditions(conditions);
+
+            // Set the OpenSaml2 XMLObject instance
+            xmlObject = saml2;
+        }
+    }
 
 }

Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/SAMLCallback.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/SAMLCallback.java?rev=1196030&r1=1196029&r2=1196030&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/SAMLCallback.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/SAMLCallback.java Tue Nov  1 14:46:06 2011
@@ -25,6 +25,7 @@ import org.apache.ws.security.saml.ext.b
 import org.apache.ws.security.saml.ext.bean.ConditionsBean;
 import org.apache.ws.security.saml.ext.bean.SubjectBean;
 import org.opensaml.common.SAMLVersion;
+import org.w3c.dom.Element;
 
 import javax.security.auth.callback.Callback;
 import java.util.ArrayList;
@@ -33,9 +34,9 @@ import java.util.List;
 
 /**
  * Class SAMLCallback will be called by the <code>AssertionWrapper</code> during the creation
- * of SAML statements (authentication, attribute, and authz decision).
- * <p/>
- * Created on May 18, 2009
+ * of SAML statements (authentication, attribute, and authz decision). Alternatively, the
+ * "assertionElement" member of this class can be set instead, for a pre-existing SAML
+ * Assertion.
  */
 public class SAMLCallback implements Callback {
     
@@ -73,6 +74,11 @@ public class SAMLCallback implements Cal
      * A list of <code>AuthDecisionStatementBean</code> values
      */
     private List<AuthDecisionStatementBean> authDecisionStatementData;
+    
+    /**
+     * A DOM Element representation of this SAML Assertion
+     */
+    private Element assertionElement;
 
     /**
      * Constructor SAMLCallback creates a new SAMLCallback instance.
@@ -220,4 +226,20 @@ public class SAMLCallback implements Cal
     public SAMLVersion getSamlVersion() {
         return samlVersion;
     }
+    
+    /**
+     * Set the DOM representation of this SAML Assertion
+     * @param assertionElement the DOM representation of this SAML Assertion
+     */
+    public void setAssertionElement(Element assertionElement) {
+        this.assertionElement = assertionElement;
+    }
+    
+    /**
+     * Get the DOM representation of this SAML Assertion
+     * @return the DOM representation of this SAML Assertion
+     */
+    public Element getAssertionElement() {
+        return assertionElement;
+    }
 }

Added: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/SAMLElementCallbackHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/SAMLElementCallbackHandler.java?rev=1196030&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/SAMLElementCallbackHandler.java (added)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/SAMLElementCallbackHandler.java Tue Nov  1 14:46:06 2011
@@ -0,0 +1,81 @@
+/**
+ * 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.common;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.saml.ext.SAMLCallback;
+import org.apache.ws.security.saml.ext.SAMLParms;
+import org.apache.ws.security.saml.ext.builder.SAML1Constants;
+import org.w3c.dom.Element;
+
+/**
+ * A Callback Handler implementation for a SAML 1.1 assertion. Rather than create a set of beans
+ * that AssertionWrapper will use to create a SAML Assertion, it sets a DOM Element directly on
+ * the SAMLCallback object.
+ */
+public class SAMLElementCallbackHandler extends AbstractSAMLCallbackHandler {
+    
+    public SAMLElementCallbackHandler() {
+        subjectName = "uid=joe,ou=people,ou=saml-demo,o=example.com";
+        subjectQualifier = "www.example.com";
+        confirmationMethod = SAML1Constants.CONF_SENDER_VOUCHES;
+    }
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof SAMLCallback) {
+                SAMLCallback callback = (SAMLCallback) callbacks[i];
+                Element assertionElement;
+                try {
+                    assertionElement = getSAMLAssertion();
+                } catch (Exception e) {
+                    throw new IOException(e);
+                }
+                callback.setAssertionElement(assertionElement);
+                
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+    
+    /**
+     * Mock up a SAML Assertion by using another SAMLCallbackHandler
+     * @throws Exception 
+     */
+    private Element getSAMLAssertion() throws Exception {
+        SAMLParms parms = new SAMLParms();
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setIssuer(issuer);
+        parms.setCallbackHandler(callbackHandler);
+        AssertionWrapper assertionWrapper = new AssertionWrapper(parms);
+        
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        return assertionWrapper.toDOM(factory.newDocumentBuilder().newDocument());
+    }
+    
+}

Modified: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenTest.java?rev=1196030&r1=1196029&r2=1196030&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenTest.java (original)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenTest.java Tue Nov  1 14:46:06 2011
@@ -28,6 +28,7 @@ import org.apache.ws.security.common.Cus
 import org.apache.ws.security.common.CustomSamlAssertionValidator;
 import org.apache.ws.security.common.SAML1CallbackHandler;
 import org.apache.ws.security.common.SAML2CallbackHandler;
+import org.apache.ws.security.common.SAMLElementCallbackHandler;
 import org.apache.ws.security.common.SOAPUtil;
 import org.apache.ws.security.handler.RequestData;
 import org.apache.ws.security.handler.WSHandlerConstants;
@@ -140,6 +141,45 @@ public class SamlTokenTest extends org.j
     }
     
     /**
+     * Test that creates, sends and processes an unsigned SAML 1.1 authentication assertion.
+     * It set a DOM Element on the CallbackHandler rather than creating a set of beans for
+     * AssertionWrapper to parse.
+     */
+    @org.junit.Test
+    public void testSAML1AuthnAssertionViaElement() throws Exception {
+        SAMLElementCallbackHandler callbackHandler = new SAMLElementCallbackHandler();
+        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()) {
+            LOG.debug("SAML 1.1 Authn Assertion (sender vouches - from an Element):");
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
+            LOG.debug(outputString);
+        }
+        
+        List<WSSecurityEngineResult> results = verify(unsignedDoc);
+        WSSecurityEngineResult actionResult =
+            WSSecurityUtil.fetchActionResult(results, WSConstants.ST_UNSIGNED);
+        AssertionWrapper receivedAssertion = 
+            (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+        assertTrue(receivedAssertion != null);
+        assertTrue(!receivedAssertion.isSigned());
+        assertTrue(receivedAssertion.getSignatureValue() == null);
+    }
+    
+    /**
      * Test that creates, sends and processes an unsigned SAML 1.1 attribute assertion.
      */
     @org.junit.Test