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