Drive relying party endpoint selection off of metadata
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sun, 17 Jun 2007 14:27:07 +0000 (14:27 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sun, 17 Jun 2007 14:27:07 +0000 (14:27 +0000)
SAML 2 SSO bug fixes and working unit tests
Carry party metadata in requests contexts

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2248 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

resources/classpath/schema/shibboleth-2.0-idp-profile.xsd
src/edu/internet2/middleware/shibboleth/idp/config/profile/SAML2SSOProfileHandlerBeanDefinitionParser.java
src/edu/internet2/middleware/shibboleth/idp/profile/AbstractSAMLProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/AbstractSAML1ProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/AttributeQueryProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/ShibbolethSSOProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AbstractSAML2ProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AttributeQueryProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/SSOProfileHandler.java
tests/edu/internet2/middleware/shibboleth/idp/system/conf1/SAML2SSOTestCase.java

index c6081a9..02216a8 100644 (file)
                         </xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
-                <xsd:attribute name="encodingBinding" type="xsd:anyURI"
-                    default="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
-                    <xsd:annotation>
-                        <xsd:documentation>
-                            The URI of the binding used when encoding responses to relying parties.
-                        </xsd:documentation>
-                    </xsd:annotation>
-                </xsd:attribute>
                 <xsd:attribute name="securityPolicyFactoryId" type="xsd:string"
                     default="shibboleth.SAML2SSOMessageSecurityPolicyFactory">
                     <xsd:annotation>
index 03dab83..3468635 100644 (file)
@@ -46,8 +46,6 @@ public class SAML2SSOProfileHandlerBeanDefinitionParser extends AbstractSAML2Pro
 
         builder.addConstructorArg(DatatypeHelper.safeTrimOrNullString(config.getAttributeNS(null, "decodingBinding")));
 
-        builder.addConstructorArg(DatatypeHelper.safeTrimOrNullString(config.getAttributeNS(null, "encodingBinding")));
-
         builder.addPropertyReference("securityPolicyFactory", DatatypeHelper.safeTrimOrNullString(config
                 .getAttributeNS(null, "securityPolicyFactoryId")));
     }
index 0fcac40..f6a712d 100644 (file)
@@ -19,13 +19,14 @@ package edu.internet2.middleware.shibboleth.idp.profile;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-import javax.xml.namespace.QName;
 
 import org.apache.log4j.Logger;
 import org.opensaml.common.IdentifierGenerator;
 import org.opensaml.common.SAMLObject;
 import org.opensaml.common.binding.decoding.MessageDecoderFactory;
 import org.opensaml.common.binding.encoding.MessageEncoderFactory;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.provider.MetadataProvider;
 
 import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
@@ -66,13 +67,13 @@ public abstract class AbstractSAMLProfileHandler extends
     public IdentifierGenerator getIdGenerator() {
         return idGenerator;
     }
-    
+
     /**
      * Gets an ID generator which may be used for SAML assertions, requests, etc.
      * 
      * @param generator an ID generator which may be used for SAML assertions, requests, etc
      */
-    public void setIdGenerator(IdentifierGenerator generator){
+    public void setIdGenerator(IdentifierGenerator generator) {
         idGenerator = generator;
     }
 
@@ -150,20 +151,26 @@ public abstract class AbstractSAMLProfileHandler extends
 
         return null;
     }
-    
+
     /**
      * Contextual object used to accumlate information as profile requests are being processed.
      * 
      * @param <StatusType> type of Status object
      */
     protected class SAMLProfileRequestContext<StatusType extends SAMLObject> extends ShibbolethProfileRequestContext {
-        
-        /** Role descriptor name that the asserting party is operating in. */
-        private QName assertingPartyRole;
-        
-        /** Role descriptor name that the relying party is operating in. */
-        private QName relyingPartyRole;
-        
+
+        /** Entity descriptor for the asserting party. */
+        private EntityDescriptor assertingPartyMetadata;
+
+        /** Role descriptor meatadata for the asserting party. */
+        private RoleDescriptor assertingPartyRoleMetadata;
+
+        /** Entity descriptor for the relying party. */
+        private EntityDescriptor relyingPartyMetadata;
+
+        /** Role descriptor meatadata for the relying party. */
+        private RoleDescriptor relyingPartyRoleMetadata;
+
         /**
          * Constructor.
          * 
@@ -176,39 +183,75 @@ public abstract class AbstractSAMLProfileHandler extends
         }
 
         /**
-         * Gets the role descriptor name that the asserting party is operating in.
+         * Gets the metadata for the asserting party.
+         * 
+         * @return metadata for the asserting party
+         */
+        public EntityDescriptor getAssertingPartyMetadata() {
+            return assertingPartyMetadata;
+        }
+
+        /**
+         * Sets the metadata for the asserting party.
+         * 
+         * @param metadata metadata for the asserting party
+         */
+        public void setAssertingPartyMetadata(EntityDescriptor metadata) {
+            assertingPartyMetadata = metadata;
+        }
+
+        /**
+         * Gets the role descriptor for the asserting party.
+         * 
+         * @return role descriptor for the asserting party
+         */
+        public RoleDescriptor getAssertingPartyRoleMetadata() {
+            return assertingPartyRoleMetadata;
+        }
+
+        /**
+         * Sets the role descriptor for the asserting party.
+         * 
+         * @param descriptor role descriptor for the asserting party
+         */
+        public void setAssertingPartyRoleMetadata(RoleDescriptor descriptor) {
+            assertingPartyRoleMetadata = descriptor;
+        }
+
+        /**
+         * Gets the metadata for the relying party.
          * 
-         * @return role descriptor name that the asserting party is operating in
+         * @return metadata for the relying party
          */
-        public QName getAssertingPartyRole() {
-            return assertingPartyRole;
+        public EntityDescriptor getRelyingPartyMetadata() {
+            return relyingPartyMetadata;
         }
 
         /**
-         * Sets the role descriptor name that the asserting party is operating in.
+         * Sets the metadata for the relying party.
          * 
-         * @param role role descriptor name that the asserting party is operating in
+         * @param metadata metadata for the relying party
          */
-        public void setAssertingPartyRole(QName role) {
-            assertingPartyRole = role;
+        public void setRelyingPartyMetadata(EntityDescriptor metadata) {
+            relyingPartyMetadata = metadata;
         }
 
         /**
-         * Gets the role descriptor name that the relying party is operating in.
+         * Gets the role descriptor for the relying party.
          * 
-         * @return role descriptor name that the relying party is operating in
+         * @return role descriptor for the relying party
          */
-        public QName getRelyingPartyRole() {
-            return relyingPartyRole;
+        public RoleDescriptor getRelyingPartyRoleMetadata() {
+            return relyingPartyRoleMetadata;
         }
 
         /**
-         * Sets the role descriptor name that the relying party is operating in.
+         * Sets the role descriptor for the relying party.
          * 
-         * @param role role descriptor name that the relying party is operating in
+         * @param descriptor role descriptor for the relying party
          */
-        public void setRelyingPartyRole(QName role) {
-            relyingPartyRole = role;
+        public void setRelyingPartyRoleMetadata(RoleDescriptor descriptor) {
+            relyingPartyRoleMetadata = descriptor;
         }
     }
 }
\ No newline at end of file
index cc8459e..8c7ee87 100644 (file)
@@ -30,7 +30,6 @@ import org.opensaml.common.SAMLObject;
 import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.SAMLVersion;
 import org.opensaml.common.impl.SAMLObjectContentReference;
-import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.log.Level;
 import org.opensaml.saml1.core.Assertion;
 import org.opensaml.saml1.core.AttributeQuery;
@@ -40,7 +39,6 @@ import org.opensaml.saml1.core.AudienceRestrictionCondition;
 import org.opensaml.saml1.core.Conditions;
 import org.opensaml.saml1.core.ConfirmationMethod;
 import org.opensaml.saml1.core.NameIdentifier;
-import org.opensaml.saml1.core.Query;
 import org.opensaml.saml1.core.RequestAbstractType;
 import org.opensaml.saml1.core.Response;
 import org.opensaml.saml1.core.ResponseAbstractType;
@@ -57,7 +55,6 @@ import org.opensaml.saml2.metadata.PDPDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.SPSSODescriptor;
 import org.opensaml.saml2.metadata.SSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.xml.XMLObjectBuilder;
 import org.opensaml.xml.security.credential.Credential;
 import org.opensaml.xml.signature.Signature;
@@ -473,29 +470,21 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
     protected List<String> getNameFormats(SAML1ProfileRequestContext requestContext) throws ProfileException {
         ArrayList<String> nameFormats = new ArrayList<String>();
 
-        try {
-            RoleDescriptor assertingPartyRole = getMetadataProvider().getRole(requestContext.getAssertingPartyId(),
-                    requestContext.getAssertingPartyRole(), SAMLConstants.SAML1P_NS);
-            List<String> assertingPartySupportedFormats = getEntitySupportedFormats(assertingPartyRole);
-
-            if (nameFormats.isEmpty()) {
-                RoleDescriptor relyingPartyRole = getMetadataProvider().getRole(requestContext.getRelyingPartyId(),
-                        requestContext.getRelyingPartyRole(), SAMLConstants.SAML1P_NS);
-                List<String> relyingPartySupportedFormats = getEntitySupportedFormats(relyingPartyRole);
-
-                assertingPartySupportedFormats.retainAll(relyingPartySupportedFormats);
-                nameFormats.addAll(assertingPartySupportedFormats);
-            }
-            if (nameFormats.isEmpty()) {
-                nameFormats.add("urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified");
-            }
+        RoleDescriptor assertingPartyRole = requestContext.getAssertingPartyRoleMetadata();
+        List<String> assertingPartySupportedFormats = getEntitySupportedFormats(assertingPartyRole);
 
-            return nameFormats;
+        if (nameFormats.isEmpty()) {
+            RoleDescriptor relyingPartyRole = requestContext.getRelyingPartyRoleMetadata();
+            List<String> relyingPartySupportedFormats = getEntitySupportedFormats(relyingPartyRole);
 
-        } catch (MetadataProviderException e) {
-            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Unable to lookup metadata"));
-            throw new ProfileException("Unable to determine lookup entity metadata", e);
+            assertingPartySupportedFormats.retainAll(relyingPartySupportedFormats);
+            nameFormats.addAll(assertingPartySupportedFormats);
         }
+        if (nameFormats.isEmpty()) {
+            nameFormats.add("urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified");
+        }
+
+        return nameFormats;
     }
 
     /**
@@ -734,14 +723,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
 
         boolean signAssertion = false;
 
-        RoleDescriptor relyingPartyRole;
-        try {
-            relyingPartyRole = getMetadataProvider().getRole(requestContext.getRelyingPartyId(),
-                    requestContext.getRelyingPartyRole(), SAMLConstants.SAML20P_NS);
-        } catch (MetadataProviderException e) {
-            throw new ProfileException("Unable to lookup entity metadata for relying party "
-                    + requestContext.getRelyingPartyId());
-        }
+        RoleDescriptor relyingPartyRole = requestContext.getRelyingPartyRoleMetadata();
         AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
 
         if (relyingPartyRole instanceof SPSSODescriptor) {
index e3cacc8..e97027c 100644 (file)
@@ -26,14 +26,14 @@ import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.decoding.MessageDecoder;
 import org.opensaml.common.binding.encoding.MessageEncoder;
 import org.opensaml.common.binding.security.SAMLSecurityPolicy;
+import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml1.binding.decoding.HTTPSOAP11Decoder;
 import org.opensaml.saml1.binding.encoding.HTTPSOAP11Encoder;
 import org.opensaml.saml1.core.AttributeQuery;
 import org.opensaml.saml1.core.Response;
 import org.opensaml.saml1.core.Statement;
 import org.opensaml.saml1.core.StatusCode;
-import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.ws.security.SecurityPolicyException;
 
 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
@@ -117,19 +117,34 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
             SAMLSecurityPolicy securityPolicy = requestContext.getMessageDecoder().getSecurityPolicy();
             requestContext.setRelyingPartyId(securityPolicy.getIssuer());
 
-            RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(requestContext.getRelyingPartyId());
-            requestContext.setRelyingPartyConfiguration(rpConfig);
+            try {
+                requestContext.setRelyingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                        requestContext.getRelyingPartyId()));
 
-            requestContext.setRelyingPartyRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+                requestContext.setRelyingPartyRoleMetadata(requestContext.getRelyingPartyMetadata().getSPSSODescriptor(
+                        SAMLConstants.SAML1P_NS));
 
-            requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
+                RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(requestContext.getRelyingPartyId());
+                requestContext.setRelyingPartyConfiguration(rpConfig);
 
-            requestContext.setAssertingPartyRole(AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
+                requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
 
-            requestContext.setProfileConfiguration((AttributeQueryConfiguration) rpConfig
-                    .getProfileConfiguration(AttributeQueryConfiguration.PROFILE_ID));
+                requestContext.setAssertingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                        requestContext.getAssertingPartyId()));
 
-            requestContext.setSamlRequest((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
+                requestContext.setAssertingPartyRoleMetadata(requestContext.getAssertingPartyMetadata()
+                        .getAttributeAuthorityDescriptor(SAMLConstants.SAML1P_NS));
+
+                requestContext.setProfileConfiguration((AttributeQueryConfiguration) rpConfig
+                        .getProfileConfiguration(AttributeQueryConfiguration.PROFILE_ID));
+
+                requestContext.setSamlRequest((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
+            } catch (MetadataProviderException e) {
+                log.error("Unable to locate metadata for asserting or relying party");
+                requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null,
+                        "Error locating party metadata"));
+                throw new ProfileException("Error locating party metadata");
+            }
         }
     }
 
index aa098bf..f69a884 100644 (file)
@@ -34,13 +34,13 @@ import org.opensaml.common.SAMLObject;
 import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.encoding.MessageEncoder;
+import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml1.core.AuthenticationStatement;
 import org.opensaml.saml1.core.Response;
 import org.opensaml.saml1.core.Statement;
 import org.opensaml.saml1.core.StatusCode;
 import org.opensaml.saml1.core.Subject;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.xml.util.DatatypeHelper;
 
 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
@@ -239,9 +239,11 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
      * @param response current response
      * 
      * @return created authentication request context
+     * 
+     * @throws ProfileException thrown if asserting and relying party metadata can not be located
      */
     protected ShibbolethSSORequestContext buildRequestContext(ShibbolethSSOLoginContext loginContext,
-            ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response) {
+            ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response) throws ProfileException {
         ShibbolethSSORequestContext requestContext = new ShibbolethSSORequestContext(request, response);
 
         requestContext.setLoginContext(loginContext);
@@ -254,19 +256,34 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
 
         requestContext.setRelyingPartyId(relyingPartyId);
 
-        RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
-        requestContext.setRelyingPartyConfiguration(rpConfig);
+        try {
+
+            requestContext.setRelyingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                    requestContext.getRelyingPartyId()));
 
-        requestContext.setRelyingPartyRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+            requestContext.setRelyingPartyRoleMetadata(requestContext.getRelyingPartyMetadata().getSPSSODescriptor(
+                    SAMLConstants.SAML1P_NS));
 
-        requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
+            RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
+            requestContext.setRelyingPartyConfiguration(rpConfig);
 
-        requestContext.setAssertingPartyRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+            requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
 
-        requestContext.setProfileConfiguration((ShibbolethSSOConfiguration) rpConfig
-                .getProfileConfiguration(ShibbolethSSOConfiguration.PROFILE_ID));
+            requestContext.setAssertingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                    requestContext.getAssertingPartyId()));
 
-        return requestContext;
+            requestContext.setAssertingPartyRoleMetadata(requestContext.getAssertingPartyMetadata()
+                    .getIDPSSODescriptor(SAMLConstants.SAML1P_NS));
+
+            requestContext.setProfileConfiguration((ShibbolethSSOConfiguration) rpConfig
+                    .getProfileConfiguration(ShibbolethSSOConfiguration.PROFILE_ID));
+
+            return requestContext;
+        } catch (MetadataProviderException e) {
+            log.error("Unable to locate metadata for asserting or relying party");
+            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error locating party metadata"));
+            throw new ProfileException("Error locating party metadata");
+        }
     }
 
     /**
index 3b79a12..0f8347b 100644 (file)
@@ -29,7 +29,6 @@ import org.joda.time.DateTime;
 import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.SAMLVersion;
 import org.opensaml.common.impl.SAMLObjectContentReference;
-import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.log.Level;
 import org.opensaml.saml2.core.Advice;
 import org.opensaml.saml2.core.Assertion;
@@ -58,7 +57,6 @@ import org.opensaml.saml2.metadata.PDPDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.SPSSODescriptor;
 import org.opensaml.saml2.metadata.SSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.xml.XMLObjectBuilder;
 import org.opensaml.xml.security.credential.Credential;
 import org.opensaml.xml.signature.Signature;
@@ -589,18 +587,10 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
 
         boolean signAssertion = false;
 
-        RoleDescriptor relyingPartyRole;
-        try {
-            relyingPartyRole = getMetadataProvider().getRole(requestContext.getRelyingPartyId(),
-                    requestContext.getRelyingPartyRole(), SAMLConstants.SAML20P_NS);
-        } catch (MetadataProviderException e) {
-            throw new ProfileException("Unable to lookup entity metadata for relying party "
-                    + requestContext.getRelyingPartyId());
-        }
         AbstractSAML2ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
 
-        if (relyingPartyRole instanceof SPSSODescriptor) {
-            SPSSODescriptor ssoDescriptor = (SPSSODescriptor) relyingPartyRole;
+        if (requestContext.getRelyingPartyRoleMetadata() instanceof SPSSODescriptor) {
+            SPSSODescriptor ssoDescriptor = (SPSSODescriptor) requestContext.getRelyingPartyRoleMetadata();
             if (ssoDescriptor.getWantAssertionsSigned() != null) {
                 signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
                 if (log.isDebugEnabled()) {
@@ -770,45 +760,36 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     protected List<String> getNameFormats(SAML2ProfileRequestContext requestContext) throws ProfileException {
         ArrayList<String> nameFormats = new ArrayList<String>();
 
-        try {
-            RoleDescriptor assertingPartyRole = getMetadataProvider().getRole(requestContext.getAssertingPartyId(),
-                    requestContext.getAssertingPartyRole(), SAMLConstants.SAML20P_NS);
-            List<String> assertingPartySupportedFormats = getEntitySupportedFormats(assertingPartyRole);
-
-            String nameFormat = null;
-            if (requestContext.getSamlRequest() instanceof AuthnRequest) {
-                AuthnRequest authnRequest = (AuthnRequest) requestContext.getSamlRequest();
-                if (authnRequest.getNameIDPolicy() != null) {
-                    nameFormat = authnRequest.getNameIDPolicy().getFormat();
-                    if (assertingPartySupportedFormats.contains(nameFormat)) {
-                        nameFormats.add(nameFormat);
-                    } else {
-                        requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI,
-                                StatusCode.INVALID_NAMEID_POLICY_URI, "Format not supported: " + nameFormat));
-                        throw new ProfileException("NameID format required by relying party is not supported");
-                    }
+        List<String> assertingPartySupportedFormats = getEntitySupportedFormats(requestContext
+                .getAssertingPartyRoleMetadata());
+
+        String nameFormat = null;
+        if (requestContext.getSamlRequest() instanceof AuthnRequest) {
+            AuthnRequest authnRequest = (AuthnRequest) requestContext.getSamlRequest();
+            if (authnRequest.getNameIDPolicy() != null) {
+                nameFormat = authnRequest.getNameIDPolicy().getFormat();
+                if (assertingPartySupportedFormats.contains(nameFormat)) {
+                    nameFormats.add(nameFormat);
+                } else {
+                    requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI,
+                            StatusCode.INVALID_NAMEID_POLICY_URI, "Format not supported: " + nameFormat));
+                    throw new ProfileException("NameID format required by relying party is not supported");
                 }
             }
+        }
 
-            if (nameFormats.isEmpty()) {
-                RoleDescriptor relyingPartyRole = getMetadataProvider().getRole(requestContext.getRelyingPartyId(),
-                        requestContext.getRelyingPartyRole(), SAMLConstants.SAML20P_NS);
-                List<String> relyingPartySupportedFormats = getEntitySupportedFormats(relyingPartyRole);
-
-                assertingPartySupportedFormats.retainAll(relyingPartySupportedFormats);
-                nameFormats.addAll(assertingPartySupportedFormats);
-            }
-            if (nameFormats.isEmpty()) {
-                nameFormats.add("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified");
-            }
-
-            return nameFormats;
+        if (nameFormats.isEmpty()) {
+            List<String> relyingPartySupportedFormats = getEntitySupportedFormats(requestContext
+                    .getRelyingPartyRoleMetadata());
 
-        } catch (MetadataProviderException e) {
-            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null,
-                    "Unable to lookup entity metadata"));
-            throw new ProfileException("Unable to determine lookup entity metadata", e);
+            assertingPartySupportedFormats.retainAll(relyingPartySupportedFormats);
+            nameFormats.addAll(assertingPartySupportedFormats);
+        }
+        if (nameFormats.isEmpty()) {
+            nameFormats.add("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified");
         }
+
+        return nameFormats;
     }
 
     /**
index 4f681bd..8e85a30 100644 (file)
@@ -26,14 +26,14 @@ import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.decoding.MessageDecoder;
 import org.opensaml.common.binding.encoding.MessageEncoder;
 import org.opensaml.common.binding.security.SAMLSecurityPolicy;
+import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.binding.decoding.HTTPSOAP11Decoder;
 import org.opensaml.saml2.core.AttributeQuery;
 import org.opensaml.saml2.core.Response;
 import org.opensaml.saml2.core.Statement;
 import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.saml2.core.Subject;
-import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.ws.security.SecurityPolicyException;
 
 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
@@ -65,9 +65,9 @@ public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
         Response samlResponse;
         try {
             decodeRequest(requestContext);
-            
+
             checkSamlVersion(requestContext);
-            
+
             // Resolve attribute query name id to principal name and place in context
             resolvePrincipal(requestContext);
 
@@ -131,19 +131,34 @@ public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
             SAMLSecurityPolicy securityPolicy = requestContext.getMessageDecoder().getSecurityPolicy();
             requestContext.setRelyingPartyId(securityPolicy.getIssuer());
 
-            RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(requestContext.getRelyingPartyId());
-            requestContext.setRelyingPartyConfiguration(rpConfig);
+            try {
+                requestContext.setRelyingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                        requestContext.getRelyingPartyId()));
+
+                requestContext.setRelyingPartyRoleMetadata(requestContext.getRelyingPartyMetadata().getSPSSODescriptor(
+                        SAMLConstants.SAML20P_NS));
 
-            requestContext.setRelyingPartyRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+                RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(requestContext.getRelyingPartyId());
+                requestContext.setRelyingPartyConfiguration(rpConfig);
 
-            requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
+                requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
 
-            requestContext.setAssertingPartyRole(AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
+                requestContext.setAssertingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                        requestContext.getAssertingPartyId()));
 
-            requestContext.setProfileConfiguration((AttributeQueryConfiguration) rpConfig
-                    .getProfileConfiguration(AttributeQueryConfiguration.PROFILE_ID));
+                requestContext.setAssertingPartyRoleMetadata(requestContext.getAssertingPartyMetadata()
+                        .getAttributeAuthorityDescriptor(SAMLConstants.SAML20P_NS));
 
-            requestContext.setSamlRequest((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
+                requestContext.setProfileConfiguration((AttributeQueryConfiguration) rpConfig
+                        .getProfileConfiguration(AttributeQueryConfiguration.PROFILE_ID));
+
+                requestContext.setSamlRequest((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
+            } catch (MetadataProviderException e) {
+                log.error("Unable to locate metadata for asserting or relying party");
+                requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null,
+                        "Error locating party metadata"));
+                throw new ProfileException("Error locating party metadata");
+            }
         }
     }
 
index ebbbcd0..7e7dedf 100644 (file)
@@ -32,6 +32,8 @@ import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.decoding.MessageDecoder;
 import org.opensaml.common.binding.encoding.MessageEncoder;
 import org.opensaml.common.binding.security.SAMLSecurityPolicy;
+import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.binding.AuthnResponseEndpointSelector;
 import org.opensaml.saml2.core.AuthnContext;
 import org.opensaml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml2.core.AuthnContextDeclRef;
@@ -42,8 +44,9 @@ import org.opensaml.saml2.core.Response;
 import org.opensaml.saml2.core.Statement;
 import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.saml2.core.Subject;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml2.metadata.Endpoint;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.ws.security.SecurityPolicyException;
 import org.opensaml.xml.io.MarshallingException;
 import org.opensaml.xml.io.UnmarshallingException;
@@ -80,27 +83,22 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
     /** URI of request decoder. */
     private String decodingBinding;
 
-    /** URI of response encoder. */
-    private String encodingBinding;
-
     /**
      * Constructor.
      * 
      * @param authnManagerPath path to the authentication manager servlet
      * @param decoder URI of the request decoder to use
-     * @param encoder URI of the response encoder to use
      */
     @SuppressWarnings("unchecked")
-    public SSOProfileHandler(String authnManagerPath, String decoder, String encoder) {
+    public SSOProfileHandler(String authnManagerPath, String decoder) {
         super();
 
-        if (authnManagerPath == null || decoder == null || encoder == null) {
-            throw new IllegalArgumentException("AuthN manager path, decoding, encoding bindings URI may not be null");
+        if (authnManagerPath == null || decoder == null) {
+            throw new IllegalArgumentException("AuthN manager path or decoding bindings URI may not be null");
         }
 
         authenticationManagerPath = authnManagerPath;
         decodingBinding = decoder;
-        encodingBinding = encoder;
 
         authnStatementBuilder = (SAMLObjectBuilder<AuthnStatement>) getBuilderFactory().getBuilder(
                 AuthnStatement.DEFAULT_ELEMENT_NAME);
@@ -227,7 +225,7 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
         httpSession.removeAttribute(LoginContext.LOGIN_CONTEXT_KEY);
 
         SSORequestContext requestContext = buildRequestContext(loginContext, request, response);
-        
+
         checkSamlVersion(requestContext);
 
         Response samlResponse;
@@ -303,22 +301,31 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
         SSORequestContext requestContext = new SSORequestContext(request, response);
 
         try {
+            requestContext.setMessageDecoder(getMessageDecoderFactory().getMessageDecoder(decodingBinding));
+
             requestContext.setLoginContext(loginContext);
-            
+
             String relyingPartyId = loginContext.getRelyingPartyId();
             AuthnRequest authnRequest = loginContext.getAuthenticationRequest();
 
             requestContext.setRelyingPartyId(relyingPartyId);
 
+            requestContext.setRelyingPartyMetadata(getMetadataProvider().getEntityDescriptor(relyingPartyId));
+
+            requestContext.setRelyingPartyRoleMetadata(requestContext.getRelyingPartyMetadata().getSPSSODescriptor(
+                    SAMLConstants.SAML20P_NS));
+
             RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
             requestContext.setRelyingPartyConfiguration(rpConfig);
 
-            requestContext.setRelyingPartyRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
-
             requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
 
-            requestContext.setAssertingPartyRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
-            
+            requestContext.setAssertingPartyMetadata(getMetadataProvider().getEntityDescriptor(
+                    requestContext.getAssertingPartyId()));
+
+            requestContext.setAssertingPartyRoleMetadata(requestContext.getRelyingPartyMetadata().getIDPSSODescriptor(
+                    SAMLConstants.SAML20P_NS));
+
             requestContext.setPrincipalName(loginContext.getPrincipalName());
 
             requestContext.setProfileConfiguration((SSOConfiguration) rpConfig
@@ -332,6 +339,11 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null,
                     "Error recovering request state"));
             throw new ProfileException("Error recovering request state", e);
+        } catch (MetadataProviderException e) {
+            log.error("Unable to locate metadata for asserting or relying party");
+            requestContext
+                    .setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null, "Error locating party metadata"));
+            throw new ProfileException("Error locating party metadata");
         }
     }
 
@@ -417,13 +429,28 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
             log.debug("Encoding response to SAML request " + requestContext.getSamlRequest().getID()
                     + " from relying party " + requestContext.getRelyingPartyId());
         }
-        MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(encodingBinding);
+        AuthnResponseEndpointSelector endpointSelector = new AuthnResponseEndpointSelector();
+        endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+        endpointSelector.setMetadataProvider(getMetadataProvider());
+        endpointSelector.setRelyingParty(requestContext.getRelyingPartyMetadata());
+        endpointSelector.setRelyingPartyRole(requestContext.getRelyingPartyRoleMetadata());
+        endpointSelector.setSamlRequest(requestContext.getSamlRequest());
+        endpointSelector.getSupportedIssuerBindings().addAll(getMessageEncoderFactory().getEncoderBuilders().keySet());
+        Endpoint relyingPartyEndpoint = endpointSelector.selectEndpoint();
+
+        MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(
+                relyingPartyEndpoint.getBinding());
         if (encoder == null) {
-            log.error("No response encoder was registered for binding type: " + encodingBinding);
-            throw new ProfileException("No response encoder was registered for binding type: " + encodingBinding);
+            log.error("No response encoder was registered for binding type: " + relyingPartyEndpoint.getBinding());
+            throw new ProfileException("No response encoder was registered for binding type: "
+                    + relyingPartyEndpoint.getBinding());
         }
 
         super.populateMessageEncoder(encoder);
+        encoder.setIssuer(requestContext.getAssertingPartyId());
+        encoder.setRelyingParty(requestContext.getRelyingPartyMetadata());
+        encoder.setRelyingPartyEndpoint(relyingPartyEndpoint);
+        encoder.setRelyingPartyRole(requestContext.getRelyingPartyRoleMetadata());
         encoder.setResponse(requestContext.getProfileResponse().getRawResponse());
         encoder.setSamlMessage(requestContext.getSamlResponse());
         requestContext.setMessageEncoder(encoder);
index 3aa92e0..88b701d 100644 (file)
 
 package edu.internet2.middleware.shibboleth.idp.system.conf1;
 
-import java.io.StringWriter;
-
 import javax.servlet.http.HttpSession;
 
 import org.joda.time.DateTime;
 import org.opensaml.common.SAMLObjectBuilder;
-import org.opensaml.common.binding.encoding.MessageEncoder;
-import org.opensaml.common.binding.encoding.MessageEncoderFactory;
 import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
-import org.opensaml.saml2.core.AttributeQuery;
 import org.opensaml.saml2.core.AuthnRequest;
 import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.xml.io.Marshaller;
 import org.opensaml.xml.io.MarshallingException;
 import org.opensaml.xml.util.Base64;
@@ -132,6 +126,7 @@ public class SAML2SSOTestCase extends BaseConf1TestCase {
         ProfileResponse profileResponse = new ShibbolethProfileResponse(servletResponse);
         handler.processRequest(profileRequest, profileResponse);
 
+        System.out.println(servletResponse.getContentAsString());
     }
 
     protected AuthnRequest buildAuthnRequest(String requester) {