[java-opensaml] branch master updated: IDP-1217 Create AssertionConsumerService from AuthnRequest extension

Rod Widdowson rdw at steadingsoftware.com
Tue Jun 19 11:09:02 EDT 2018


This is an automated email from the git hooks/post-receive script.

rdw 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=0b2e591f1b98f0f77719d992c9d7487db34f479f

The following commit(s) were added to refs/heads/master by this push:
       new  0b2e591   IDP-1217 Create AssertionConsumerService from AuthnRequest extension
0b2e591 is described below

commit 0b2e591f1b98f0f77719d992c9d7487db34f479f
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Tue Jun 19 16:06:24 2018 +0100

    IDP-1217 Create AssertionConsumerService from AuthnRequest extension
    
    https://issues.shibboleth.net/jira/browse/IDP-1217
    
    If the AuthnRequest contains the <RequestedAttributes> extension and
    does not have an AssertionConsumerServiceIndex then grow a
    disconnected AssertionConsumerService and populate it with the
    requested attributes.
---
 .../SAMLAddAttributeConsumingServiceHandler.java   | 104 ++++++++++++++++-----
 1 file changed, 83 insertions(+), 21 deletions(-)

diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLAddAttributeConsumingServiceHandler.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLAddAttributeConsumingServiceHandler.java
index 2418ab8..b21ef47 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLAddAttributeConsumingServiceHandler.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/SAMLAddAttributeConsumingServiceHandler.java
@@ -17,11 +17,18 @@
 
 package org.opensaml.saml.common.binding.impl;
 
+import java.util.List;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.core.xml.util.XMLObjectSupport.CloneOutputOption;
 import org.opensaml.messaging.context.MessageContext;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.handler.AbstractMessageHandler;
@@ -29,8 +36,11 @@ import org.opensaml.messaging.handler.MessageHandlerException;
 import org.opensaml.saml.common.messaging.context.AttributeConsumingServiceContext;
 import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
 import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.ext.reqattr.RequestedAttributes;
 import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.Extensions;
 import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,12 +60,16 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
     /** Lookup strategy for {@link SAMLMetadataContext}. */
     @Nonnull private Function<MessageContext,SAMLMetadataContext> metadataContextLookupStrategy;
    
-    /** Lookup strategy for an {@link AttributeConsumingService} index. */
-    @Nullable private Function<MessageContext,Integer> indexLookupStrategy;
+    /** Lookup strategy for an {@link AuthnRequest} index. */
+    @Nonnull private Function<MessageContext, AuthnRequest> authnRequestLookupStrategy;
 
-    /** {@link AttributeConsumingService} index. */
-    @Nullable private Integer index;
+    /** {@link AttributeConsumingService} index - if specified. */
     
+    @Nullable private Integer index;
+
+    /** {@link RequestedAttribute} list - if specified. */
+    @Nullable private List<RequestedAttribute> requestedAttributes;
+
     /**
      * Constructor.
      */
@@ -65,7 +79,7 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
                 Functions.compose(
                         new ChildContextLookup<SAMLPeerEntityContext,SAMLMetadataContext>(SAMLMetadataContext.class),
                         new ChildContextLookup<MessageContext,SAMLPeerEntityContext>(SAMLPeerEntityContext.class));
-        indexLookupStrategy = new AuthnRequestIndexLookup();
+        authnRequestLookupStrategy = new AuthnRequestLookup();
     }
 
     /**
@@ -83,9 +97,9 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
      * 
      * @param strategy lookup strategy
      */
-    public void setIndexLookupStrategy(@Nullable final Function<MessageContext,Integer> strategy) {
-        indexLookupStrategy = Constraint.isNotNull(strategy,
-                "AttributeConsumingService index lookup strategy cannot be null");
+    public void setIndexLookupStrategy(@Nullable final Function<MessageContext,AuthnRequest> strategy) {
+        authnRequestLookupStrategy = Constraint.isNotNull(strategy,
+                "AuthnRequest lookup strategy cannot be null");
     }
     
     /** {@inheritDoc} */
@@ -95,15 +109,23 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
         if (!super.doPreInvoke(messageContext)) {
             return false;
         }
-        
-        if (indexLookupStrategy != null) {
-            index = indexLookupStrategy.apply(messageContext);
+
+        final AuthnRequest authn = authnRequestLookupStrategy.apply(messageContext);
+
+        if (authn != null) {
+            index = authn.getAttributeConsumingServiceIndex();
+            requestedAttributes = getRequestedAttributes(authn);
+
+            if (index != null && requestedAttributes != null && !requestedAttributes.isEmpty()) {
+                log.info("{} AuthnRequest from {} contained a AttributeConsumingServiceIndex"
+                        + " and RequestedAttributes; ignoring the RequestedAttributes.",
+                        getLogPrefix(), authn.getProviderName());
+                requestedAttributes = null;
+            }
         }
-        
         return true;
     }
 
-// Checkstyle: ReturnCount OFF
     /** {@inheritDoc}*/
     @Override protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
         final SAMLMetadataContext metadataContext = metadataContextLookupStrategy.apply(messageContext);
@@ -128,8 +150,14 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
             }
         }
         if (null == acs) {
-            log.debug("{} Selecting default AttributeConsumingService, if any", getLogPrefix());
-            acs = ssoDescriptor.getDefaultAttributeConsumingService();
+            if (requestedAttributes != null && !requestedAttributes.isEmpty()) {
+                log.debug("{} Creating AttributeConsumingService with requested Attributes {}", 
+                        getLogPrefix(), requestedAttributes);
+                acs = attributeConsumingServiceFromRequestedAttributes();
+            } else {
+                log.debug("{} Selecting default AttributeConsumingService, if any", getLogPrefix());
+                acs = ssoDescriptor.getDefaultAttributeConsumingService();
+            }
         }
         if (null != acs) {
             log.debug("{} Selected AttributeConsumingService with index {}", getLogPrefix(), acs.getIndex());
@@ -139,23 +167,57 @@ public class SAMLAddAttributeConsumingServiceHandler extends AbstractMessageHand
             log.debug("{} No AttributeConsumingService selected", getLogPrefix());
         }
     }
-// Checkstyle: ReturnCount ON
 
-    /** Default lookup function that reads from a SAML 2 {@link AuthnRequest}. */
-    private class AuthnRequestIndexLookup implements Function<MessageContext,Integer> {
+    /** Generate an {@link AttributeConsumingService } from the {@link RequestedAttributes}.
+     * @return a suitable AttributeConsumingService
+     * @throws MessageHandlerException when the cloning failed
+     */
+    private AttributeConsumingService attributeConsumingServiceFromRequestedAttributes() 
+            throws MessageHandlerException {
+        final AttributeConsumingService newAcs = (AttributeConsumingService)
+                XMLObjectSupport.buildXMLObject(AttributeConsumingService.DEFAULT_ELEMENT_NAME);
+        for (final RequestedAttribute attribute: requestedAttributes) {
+            try {
+                newAcs.getRequestAttributes().add(
+                        XMLObjectSupport.cloneXMLObject(attribute, CloneOutputOption.DropDOM));
+            } catch (final MarshallingException | UnmarshallingException e) {
+                log.warn("{} Error cloning requested Attributes", getLogPrefix(), e);
+                throw new MessageHandlerException(e);
+            }
+        }
+        return newAcs;
+    }
+
+    /** Grab the {@link RequestedAttribute} (if any) from the {@link AuthnRequest}.
+     * @param authn the request to interrogate
+     * @return null or the list.
+     */
+    private List<RequestedAttribute> getRequestedAttributes(final AuthnRequest authn) {
+        final Extensions extensions = authn.getExtensions();
+        if (extensions == null) {
+            return null;
+        }
+        final List<XMLObject> bindings = extensions.getUnknownXMLObjects(RequestedAttributes.DEFAULT_ELEMENT_NAME);
+        if (bindings == null || bindings.isEmpty()) {
+            return null;
+        }
+        return ((RequestedAttributes)bindings.get(0)).getRequestedAttributes();
+    }
+
+    /** Default lookup function that find a SAML 2 {@link AuthnRequest}. */
+    private class AuthnRequestLookup implements Function<MessageContext,AuthnRequest> {
 
         /** {@inheritDoc} */
         @Override
-        public Integer apply(@Nullable final MessageContext input) {
+        public AuthnRequest apply(@Nullable final MessageContext input) {
             if (input != null) {
                 final Object message = input.getMessage();
                 if (message != null && message instanceof AuthnRequest) {
-                    return ((AuthnRequest) message).getAttributeConsumingServiceIndex();
+                    return (AuthnRequest) message;
                 }
             }
             
             return null;
         }
-        
     }
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list