[java-opensaml] 07/16: Work on SAMLProtocolAndRole Handler.
Brent Putman
putmanb at georgetown.edu
Fri Sep 21 22:48:45 EDT 2018
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch master
in repository java-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=bac2ca37c91c3375fe6f1a3f0ca6dc822947a5f2
commit bac2ca37c91c3375fe6f1a3f0ca6dc822947a5f2
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu Sep 20 00:21:26 2018 -0400
Work on SAMLProtocolAndRole Handler.
---
.../soap/SAMLSOAPClientContextBuilder.java | 35 ++++-
.../binding/impl/SAMLProtocolAndRoleHandler.java | 69 ++++++++--
.../binding/decoding/impl/HTTPArtifactDecoder.java | 1 +
.../impl/SAMLProtocolAndRoleHandlerTest.java | 141 +++++++++++++++++++++
4 files changed, 232 insertions(+), 14 deletions(-)
diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
index 22719ad..469e326 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
@@ -63,13 +63,16 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
/** The outbound message. **/
private OutboundMessageType outboundMessage;
+ /** The SAML protocol in use. */
+ private String protocol;
+
/** The SAML self entityID. **/
private String selfEntityID;
/** The SAML peer entityID. **/
private String peerEntityID;
- /** The SAML peer entity roles. **/
+ /** The SAML peer entity role. **/
private QName peerEntityRole;
/** The SAML peer EntityDescriptor. **/
@@ -109,6 +112,27 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
}
/**
+ * Get the SAML protocol URI.
+ *
+ * @return the SAML protocol URI
+ */
+ @Nullable public String getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * Set the SAML protocol URI.
+ *
+ * @param protocol the SAML protocol.
+ * @return this builder instance
+ */
+ @Nonnull public SAMLSOAPClientContextBuilder<InboundMessageType, OutboundMessageType> setProtocol(
+ final String uri) {
+ protocol = uri;
+ return this;
+ }
+
+ /**
* Get the SAML self entityID.
*
* @return the SAML self entityID
@@ -295,7 +319,7 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
/**
* Set the SOAP client security configuration profile ID to use.
*
- * @param profileID the profile ID, or null
+ * @param profileId the profile ID, or null
* @return this builder instance
*/
@Nonnull public SAMLSOAPClientContextBuilder<InboundMessageType, OutboundMessageType>
@@ -330,12 +354,17 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
// This is just so it's easy to change.
final BaseContext parent = opContext;
+ if (getProtocol() != null) {
+ parent.getSubcontext(SAMLProtocolContext.class, true).setProtocol(getProtocol());
+ }
+
if (getPipelineName() != null) {
parent.getSubcontext(SOAPClientContext.class, true).setPipelineName(getPipelineName());
}
if (getSecurityConfigurationProfileId() != null) {
- parent.getSubcontext(SOAPClientSecurityContext.class, true).setSecurityConfigurationProfileId(getSecurityConfigurationProfileId());
+ parent.getSubcontext(SOAPClientSecurityContext.class, true).setSecurityConfigurationProfileId(
+ getSecurityConfigurationProfileId());
}
//TODO is this required always?
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandler.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandler.java
index cf730ae..e63216a 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandler.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandler.java
@@ -18,22 +18,25 @@
package org.opensaml.saml.common.binding.impl;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
+import org.opensaml.messaging.context.BaseContext;
import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
import org.opensaml.messaging.handler.AbstractMessageHandler;
import org.opensaml.messaging.handler.MessageHandlerException;
import org.opensaml.saml.common.messaging.context.AbstractSAMLEntityContext;
import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
import org.opensaml.saml.common.messaging.context.SAMLProtocolContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
/**
* SAML {@link org.opensaml.messaging.handler.MessageHandler} that attaches protocol
* and role information to a message context via {@link SAMLProtocolContext} and
@@ -55,6 +58,20 @@ public class SAMLProtocolAndRoleHandler extends AbstractMessageHandler {
* Defaults to: {@link SAMLPeerEntityContext}. */
@Nonnull private Class<? extends AbstractSAMLEntityContext> entityContextClass = SAMLPeerEntityContext.class;
+ /** Optional lookup function for a context from which to copy the protocol and role data,
+ * for example from a parent operation context. */
+ @Nullable private ContextDataLookupFunction<MessageContext, BaseContext> copyContextLookup;
+
+ /**
+ * Set the optional lookup function for a context from which to copy the protocol and role data,
+ * for example from a parent operation context.
+ *
+ * @param lookup the lookup function, may be null
+ */
+ public void setCopyContextLookup(@Nullable final ContextDataLookupFunction<MessageContext, BaseContext> lookup) {
+ copyContextLookup = lookup;
+ }
+
/**
* Set the class type holding the SAML entity data.
*
@@ -91,16 +108,46 @@ public class SAMLProtocolAndRoleHandler extends AbstractMessageHandler {
protected void doInitialize() throws ComponentInitializationException {
super.doInitialize();
- if (samlProtocol == null || peerRole == null) {
- throw new ComponentInitializationException("SAML protocol or peer role was null");
+ if (copyContextLookup == null && (samlProtocol == null || peerRole == null)) {
+ throw new ComponentInitializationException(
+ "Either SAML protocol and peer role, or context copy function must be supplied");
}
}
/** {@inheritDoc} */
@Override
protected void doInvoke(final MessageContext messageContext) throws MessageHandlerException {
- messageContext.getSubcontext(SAMLProtocolContext.class, true).setProtocol(samlProtocol);
- messageContext.getSubcontext(entityContextClass, true).setRole(peerRole);
+
+ BaseContext copySource = null;
+ if (copyContextLookup != null) {
+ copySource = copyContextLookup.apply(messageContext);
+ }
+
+ if (samlProtocol != null) {
+ messageContext.getSubcontext(SAMLProtocolContext.class, true).setProtocol(samlProtocol);
+ } else if (copySource != null) {
+ final SAMLProtocolContext sourceProtocolContext = copySource.getSubcontext(SAMLProtocolContext.class);
+ if (sourceProtocolContext != null) {
+ messageContext.getSubcontext(SAMLProtocolContext.class, true).setProtocol(
+ sourceProtocolContext.getProtocol());
+ }
+ }
+ if (messageContext.getSubcontext(SAMLProtocolContext.class, true).getProtocol() == null) {
+ throw new MessageHandlerException("SAML protocol was not supplied and could not be dynamically resolved");
+ }
+
+ if (peerRole != null) {
+ messageContext.getSubcontext(entityContextClass, true).setRole(peerRole);
+ } else if (copySource != null) {
+ final AbstractSAMLEntityContext sourceEntityContext = copySource.getSubcontext(entityContextClass);
+ if (sourceEntityContext != null) {
+ messageContext.getSubcontext(entityContextClass, true).setRole(sourceEntityContext.getRole());
+ }
+ }
+ if (messageContext.getSubcontext(entityContextClass, true).getRole() == null) {
+ throw new MessageHandlerException("SAML role was not supplied and could not be dynamically resolved");
+ }
+
}
}
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
index a7c6b25..4ded051 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
@@ -453,6 +453,7 @@ public class HTTPArtifactDecoder extends BaseHttpServletRequestXMLMessageDecoder
final InOutOperationContext<SAMLObject, ArtifactResolve> opContext = new SAMLSOAPClientContextBuilder()
.setOutboundMessage(buildArtifactResolveRequestMessage(
artifact, ars.getLocation(), peerRoleDescriptor, selfEntityID))
+ .setProtocol(SAMLConstants.SAML20P_NS)
.setPipelineName(getSOAPPipelineName())
.setSecurityConfigurationProfileId(getSOAPClientSecurityConfigurationProfileId())
.setPeerRoleDescriptor(peerRoleDescriptor)
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandlerTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandlerTest.java
new file mode 100644
index 0000000..ea1986c
--- /dev/null
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/binding/impl/SAMLProtocolAndRoleHandlerTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.saml.common.binding.impl;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.common.messaging.context.SAMLPresenterEntityContext;
+import org.opensaml.saml.common.messaging.context.SAMLProtocolContext;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/**
+ *
+ */
+public class SAMLProtocolAndRoleHandlerTest {
+
+ private SAMLProtocolAndRoleHandler handler;
+ private MessageContext<SAMLObject> messageContext;
+
+ @BeforeMethod
+ public void setup() {
+ handler = new SAMLProtocolAndRoleHandler();
+ messageContext = new MessageContext();
+ }
+
+ @Test
+ public void testSetters() throws ComponentInitializationException, MessageHandlerException {
+ handler.setProtocol(SAMLConstants.SAML20P_NS);
+ handler.setRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ handler.initialize();
+
+ handler.invoke(messageContext);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLProtocolContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLProtocolContext.class).getProtocol(), SAMLConstants.SAML20P_NS);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLPeerEntityContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLPeerEntityContext.class).getRole(), SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Test
+ public void testSettersWithEntityClass() throws ComponentInitializationException, MessageHandlerException {
+ handler.setProtocol(SAMLConstants.SAML20P_NS);
+ handler.setRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ handler.setEntityContextClass(SAMLPresenterEntityContext.class);
+ handler.initialize();
+
+ handler.invoke(messageContext);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLProtocolContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLProtocolContext.class).getProtocol(), SAMLConstants.SAML20P_NS);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLPresenterEntityContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLPresenterEntityContext.class).getRole(), SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Test
+ public void testCopySource() throws ComponentInitializationException, MessageHandlerException {
+ handler.setCopyContextLookup(new RecursiveTypedParentContextLookup(InOutOperationContext.class));
+ handler.initialize();
+
+ final InOutOperationContext<SAMLObject, SAMLObject> opContext =
+ new InOutOperationContext<>(messageContext, new MessageContext<SAMLObject>());
+ opContext.getSubcontext(SAMLProtocolContext.class, true).setProtocol(SAMLConstants.SAML20P_NS);
+ opContext.getSubcontext(SAMLPeerEntityContext.class, true).setRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+
+ handler.invoke(messageContext);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLProtocolContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLProtocolContext.class).getProtocol(), SAMLConstants.SAML20P_NS);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLPeerEntityContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLPeerEntityContext.class).getRole(), SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Test
+ public void testCopySourceWithEntityClass() throws ComponentInitializationException, MessageHandlerException {
+ handler.setCopyContextLookup(new RecursiveTypedParentContextLookup(InOutOperationContext.class));
+ handler.setEntityContextClass(SAMLPresenterEntityContext.class);
+ handler.initialize();
+
+ final InOutOperationContext<SAMLObject, SAMLObject> opContext =
+ new InOutOperationContext<>(messageContext, new MessageContext<SAMLObject>());
+ opContext.getSubcontext(SAMLProtocolContext.class, true).setProtocol(SAMLConstants.SAML20P_NS);
+ opContext.getSubcontext(SAMLPresenterEntityContext.class, true).setRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+
+ handler.invoke(messageContext);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLProtocolContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLProtocolContext.class).getProtocol(), SAMLConstants.SAML20P_NS);
+
+ Assert.assertNotNull(messageContext.getSubcontext(SAMLPresenterEntityContext.class));
+ Assert.assertEquals(messageContext.getSubcontext(SAMLPresenterEntityContext.class).getRole(), SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Test(expectedExceptions=ComponentInitializationException.class)
+ public void testMissingConfiguredProtocol() throws ComponentInitializationException, MessageHandlerException {
+ handler.setRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ handler.setEntityContextClass(SAMLPresenterEntityContext.class);
+ handler.initialize();
+ }
+
+ @Test(expectedExceptions=ComponentInitializationException.class)
+ public void testMissingConfiguredRole() throws ComponentInitializationException, MessageHandlerException {
+ handler.setProtocol(SAMLConstants.SAML20P_NS);
+ handler.setEntityContextClass(SAMLPresenterEntityContext.class);
+ handler.initialize();
+ }
+
+ @Test(expectedExceptions=MessageHandlerException.class)
+ public void testResolverWithNoCopySource() throws ComponentInitializationException, MessageHandlerException {
+ handler.setCopyContextLookup(new RecursiveTypedParentContextLookup(InOutOperationContext.class));
+ handler.initialize();
+
+ handler.invoke(messageContext);
+ }
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list