SAML 1 Attribute Query unit test and bug fixes
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 7 Sep 2007 19:47:09 +0000 (19:47 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 7 Sep 2007 19:47:09 +0000 (19:47 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2374 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

12 files changed:
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/ArtifactResolution.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/AttributeQueryProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/BaseSAML1ProfileRequestContext.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AbstractSAML2ProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/ArtifactResolution.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AttributeQueryProfileHandler.java
test/data/conf1/attribute-resolver.xml
test/data/conf1/relying-party.xml
test/edu/internet2/middleware/shibboleth/idp/system/conf1/SAML1AttributeQueryTestCase.java [new file with mode: 0644]
test/edu/internet2/middleware/shibboleth/idp/system/conf1/ShibbolethSSOTestCase.java

index 8a965d3..8439489 100644 (file)
@@ -222,7 +222,7 @@ public abstract class AbstractSAMLProfileHandler extends
     protected void encodeResponse(BaseSAMLProfileRequestContext requestContext) throws ProfileException {
         if (log.isDebugEnabled()) {
             log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
-                    + " from relying party " + requestContext.getPeerEntityId());
+                    + " from relying party " + requestContext.getInboundMessageIssuer());
         }
 
         try {
@@ -235,7 +235,7 @@ public abstract class AbstractSAMLProfileHandler extends
             encoder.encode(requestContext);
         } catch (MessageEncodingException e) {
             throw new ProfileException("Unable to encode response to relying party: "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
         }
     }
     
@@ -250,7 +250,7 @@ public abstract class AbstractSAMLProfileHandler extends
         auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
         auditLogEntry.setPrincipalName(context.getPrincipalName());
         auditLogEntry.setAssertingPartyId(context.getLocalEntityId());
-        auditLogEntry.setRelyingPartyId(context.getPeerEntityId());
+        auditLogEntry.setRelyingPartyId(context.getInboundMessageIssuer());
         auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
         auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
         auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
index 3dc2bee..78ce8d6 100644 (file)
@@ -28,7 +28,6 @@ import org.joda.time.DateTime;
 import org.opensaml.common.SAMLObject;
 import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.SAMLVersion;
-import org.opensaml.common.impl.SAMLObjectContentReference;
 import org.opensaml.saml1.core.Assertion;
 import org.opensaml.saml1.core.AttributeQuery;
 import org.opensaml.saml1.core.AttributeStatement;
@@ -53,7 +52,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.ws.message.encoder.MessageEncodingException;
 import org.opensaml.xml.XMLObjectBuilder;
 import org.opensaml.xml.security.SecurityException;
 import org.opensaml.xml.security.SecurityHelper;
@@ -304,7 +302,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
     protected NameIdentifier buildNameId(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext)
             throws ProfileException {
         if (log.isDebugEnabled()) {
-            log.debug("Building assertion NameIdentifier to relying party " + requestContext.getPeerEntityId()
+            log.debug("Building assertion NameIdentifier to relying party " + requestContext.getInboundMessageIssuer()
                     + " for principal " + requestContext.getPrincipalName());
         }
         Map<String, BaseAttribute> principalAttributes = requestContext.getPrincipalAttributes();
@@ -492,17 +490,17 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
         try {
             if (log.isDebugEnabled()) {
                 log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
-                        + " of SAML request from relying party " + requestContext.getPeerEntityId());
+                        + " of SAML request from relying party " + requestContext.getInboundMessageIssuer());
             }
             Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
 
             requestContext.setAttributes(principalAttributes);
         } catch (AttributeRequestException e) {
             log.error("Error resolving attributes for SAML request from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
             throw new ProfileException("Error resolving attributes for SAML request from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
         }
     }
 
@@ -521,7 +519,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
 
         if (log.isDebugEnabled()) {
             log.debug("Creating attribute statement in response to SAML request from relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
 
         AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
@@ -562,7 +560,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
 
         if (log.isDebugEnabled()) {
             log.debug("Resolving principal name for subject of SAML request from relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
 
         try {
@@ -570,11 +568,11 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
             requestContext.setPrincipalName(principal);
         } catch (AttributeRequestException e) {
             log.error("Error resolving attributes for SAML request from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
                     "Error resolving principal"));
             throw new ProfileException("Error resolving attributes for SAML request from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
         }
     }
 
@@ -591,7 +589,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
     protected void signAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
             throws ProfileException {
         if (log.isDebugEnabled()) {
-            log.debug("Determining if SAML assertion to relying party " + requestContext.getPeerEntityId()
+            log.debug("Determining if SAML assertion to relying party " + requestContext.getInboundMessageIssuer()
                     + " should be signed");
         }
 
@@ -605,7 +603,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
             if (ssoDescriptor.getWantAssertionsSigned() != null) {
                 signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
                 if (log.isDebugEnabled()) {
-                    log.debug("Entity metadata for relying party " + requestContext.getPeerEntityId()
+                    log.debug("Entity metadata for relying party " + requestContext.getInboundMessageIssuer()
                             + " indicates to sign assertions: " + signAssertion);
                 }
             }
@@ -622,7 +620,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
 
         if (log.isDebugEnabled()) {
             log.debug("Determining signing credntial for assertion to relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
         Credential signatureCredential = profileConfig.getSigningCredential();
         if (signatureCredential == null) {
@@ -636,7 +634,7 @@ public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHan
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("Signing assertion to relying party " + requestContext.getPeerEntityId());
+            log.debug("Signing assertion to relying party " + requestContext.getInboundMessageIssuer());
         }
         Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
         
index 277c464..8fdf1d1 100644 (file)
@@ -84,12 +84,12 @@ public class ArtifactResolution extends AbstractSAML1ProfileHandler {
         try {
             if (requestContext.getRelyingPartyConfiguration() == null) {
                 log.error("SAML 1 Artifact resolution profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
                 requestContext.setFailureStatus(buildStatus(StatusCode.SUCCESS, StatusCode.REQUEST_DENIED,
                         "SAML 1 Artifact resolution profile is not configured for relying party "
-                                + requestContext.getPeerEntityId()));
+                                + requestContext.getInboundMessageIssuer()));
                 throw new ProfileException("SAML 1 Artifact resolution profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
             }
 
             checkSamlVersion(requestContext);
@@ -226,10 +226,10 @@ public class ArtifactResolution extends AbstractSAML1ProfileHandler {
                             + " but IdP has entity ID of " + requestContext.getLocalEntityId());
                 }
 
-                if (!artifactEntry.getRelyingPartyId().equals(requestContext.getPeerEntityId())) {
+                if (!artifactEntry.getRelyingPartyId().equals(requestContext.getInboundMessageIssuer())) {
                     log.error("Artifact requester mismatch.  Artifact was issued to "
                             + artifactEntry.getRelyingPartyId() + " but was resolve request came from "
-                            + requestContext.getPeerEntityId());
+                            + requestContext.getInboundMessageIssuer());
                 }
                 artifactMap.remove(artifact.getArtifactBytes());
                 assertions.add((Assertion) artifactEntry.getSamlMessage());
index 1a10f7a..6274aa4 100644 (file)
@@ -19,11 +19,11 @@ package edu.internet2.middleware.shibboleth.idp.profile.saml1;
 import java.util.ArrayList;
 
 import org.apache.log4j.Logger;
+import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.binding.BasicEndpointSelector;
 import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml1.core.AttributeQuery;
-import org.opensaml.saml1.core.Request;
 import org.opensaml.saml1.core.Response;
 import org.opensaml.saml1.core.Statement;
 import org.opensaml.saml1.core.StatusCode;
@@ -50,6 +50,17 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
     /** Class logger. */
     private final Logger log = Logger.getLogger(AttributeQueryProfileHandler.class);
 
+    /** Builder of assertion consumer service endpoints. */
+    private SAMLObjectBuilder<AssertionConsumerService> acsEndpointBuilder;
+
+    /** Constructor. */
+    public AttributeQueryProfileHandler() {
+        super();
+
+        acsEndpointBuilder = (SAMLObjectBuilder<AssertionConsumerService>) getBuilderFactory().getBuilder(
+                AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+    }
+
     /** {@inheritDoc} */
     public String getProfileId() {
         return "urn:mace:shibboleth:2.0:idp:profiles:saml1:query:attribute";
@@ -61,23 +72,24 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
 
         Response samlResponse;
         try {
-            if (requestContext.getRelyingPartyConfiguration() == null) {
+            if (requestContext.getProfileConfiguration() == null) {
                 log.error("SAML 1 Attribute Query profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
                 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
                         "SAML 1 Attribute Query profile is not configured for relying party "
-                                + requestContext.getPeerEntityId()));
+                                + requestContext.getInboundMessageIssuer()));
                 samlResponse = buildErrorResponse(requestContext);
+            }else{
+                resolvePrincipal(requestContext);
+                resolveAttributes(requestContext);
+                requestContext.setReleasedAttributes(requestContext.getPrincipalAttributes().keySet());
+    
+                ArrayList<Statement> statements = new ArrayList<Statement>();
+                statements.add(buildAttributeStatement(requestContext, 
+                        "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches"));
+    
+                samlResponse = buildResponse(requestContext, statements);
             }
-
-            resolvePrincipal(requestContext);
-            resolveAttributes(requestContext);
-            requestContext.setReleasedAttributes(requestContext.getPrincipalAttributes().keySet());
-            
-            ArrayList<Statement> statements = new ArrayList<Statement>();
-            statements.add(buildAttributeStatement(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches"));
-
-            samlResponse = buildResponse(requestContext, statements);
         } catch (ProfileException e) {
             samlResponse = buildErrorResponse(requestContext);
         }
@@ -109,11 +121,11 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
 
         AttributeQueryContext requestContext = new AttributeQueryContext();
         requestContext.setMetadataProvider(metadataProvider);
-        
+
         requestContext.setInboundMessageTransport(inTransport);
         requestContext.setInboundSAMLProtocol(SAMLConstants.SAML11P_NS);
         requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
-        
+
         requestContext.setOutboundMessageTransport(outTransport);
         requestContext.setOutboundSAMLProtocol(SAMLConstants.SAML11P_NS);
 
@@ -140,7 +152,8 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
         } finally {
             // Set as much information as can be retrieved from the decoded message
             try {
-                Request attributeRequest = requestContext.getInboundSAMLMessage();
+                AttributeQuery query = requestContext.getInboundSAMLMessage();
+                requestContext.setSubjectNameIdentifier(query.getSubject().getNameIdentifier());
 
                 String relyingPartyId = requestContext.getInboundMessageIssuer();
                 RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
@@ -152,16 +165,18 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
                 requestContext.setLocalEntityMetadata(metadataProvider.getEntityDescriptor(assertingPartyId));
                 requestContext.setLocalEntityRole(AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
                 requestContext.setLocalEntityRoleMetadata(requestContext.getLocalEntityMetadata()
-                        .getAttributeAuthorityDescriptor(SAMLConstants.SAML10P_NS));
+                        .getAttributeAuthorityDescriptor(SAMLConstants.SAML11P_NS));
 
                 AttributeQueryConfiguration profileConfig = (AttributeQueryConfiguration) rpConfig
                         .getProfileConfiguration(AttributeQueryConfiguration.PROFILE_ID);
-                requestContext.setProfileConfiguration(profileConfig);
-                requestContext.setOutboundMessageArtifactType(profileConfig.getOutboundArtifactType());
-                if (profileConfig.getSigningCredential() != null) {
-                    requestContext.setOutboundSAMLMessageSigningCredential(profileConfig.getSigningCredential());
-                } else if (rpConfig.getDefaultSigningCredential() != null) {
-                    requestContext.setOutboundSAMLMessageSigningCredential(rpConfig.getDefaultSigningCredential());
+                if (profileConfig != null) {
+                    requestContext.setProfileConfiguration(profileConfig);
+                    requestContext.setOutboundMessageArtifactType(profileConfig.getOutboundArtifactType());
+                    if (profileConfig.getSigningCredential() != null) {
+                        requestContext.setOutboundSAMLMessageSigningCredential(profileConfig.getSigningCredential());
+                    } else if (rpConfig.getDefaultSigningCredential() != null) {
+                        requestContext.setOutboundSAMLMessageSigningCredential(rpConfig.getDefaultSigningCredential());
+                    }
                 }
 
             } catch (MetadataProviderException e) {
@@ -181,40 +196,26 @@ public class AttributeQueryProfileHandler extends AbstractSAML1ProfileHandler {
      * @return Endpoint selected from the information provided in the request context
      */
     protected Endpoint selectEndpoint(AttributeQueryContext requestContext) {
-        BasicEndpointSelector endpointSelector = new BasicEndpointSelector();
-        endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
-        endpointSelector.setMetadataProvider(getMetadataProvider());
-        endpointSelector.setEntityMetadata(requestContext.getPeerEntityMetadata());
-        endpointSelector.setEntityRoleMetadata(requestContext.getPeerEntityRoleMetadata());
-        endpointSelector.setSamlRequest(requestContext.getInboundSAMLMessage());
-        endpointSelector.getSupportedIssuerBindings().addAll(getSupportedOutboundBindings());
-
-        return endpointSelector.selectEndpoint();
+        Endpoint endpoint;
+
+        if (getInboundBinding().equals(SAMLConstants.SAML1_SOAP11_BINDING_URI)) {
+            endpoint = acsEndpointBuilder.buildObject();
+            endpoint.setBinding(SAMLConstants.SAML1_SOAP11_BINDING_URI);
+        } else {
+            BasicEndpointSelector endpointSelector = new BasicEndpointSelector();
+            endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+            endpointSelector.setMetadataProvider(getMetadataProvider());
+            endpointSelector.setEntityMetadata(requestContext.getPeerEntityMetadata());
+            endpointSelector.setEntityRoleMetadata(requestContext.getPeerEntityRoleMetadata());
+            endpointSelector.setSamlRequest(requestContext.getInboundSAMLMessage());
+            endpointSelector.getSupportedIssuerBindings().addAll(getSupportedOutboundBindings());
+            endpoint = endpointSelector.selectEndpoint();
+        }
+
+        return endpoint;
     }
 
     /** Basic data structure used to accumulate information as a request is being processed. */
     protected class AttributeQueryContext extends
-            BaseSAML1ProfileRequestContext<Request, Response, AttributeQueryConfiguration> {
-
-        /** Current attribute query. */
-        private AttributeQuery attributeQuery;
-
-        /**
-         * Gets the attribute query of the request.
-         * 
-         * @return attribute query of the request
-         */
-        public AttributeQuery getAttributeQuery() {
-            return attributeQuery;
-        }
-
-        /**
-         * Sets the attribute query of the request.
-         * 
-         * @param query attribute query of the request
-         */
-        public void setAttributeQuery(AttributeQuery query) {
-            attributeQuery = query;
-        }
-    }
+            BaseSAML1ProfileRequestContext<AttributeQuery, Response, AttributeQueryConfiguration> {}
 }
\ No newline at end of file
index 91fa070..5d89042 100644 (file)
@@ -1,8 +1,8 @@
 
 package edu.internet2.middleware.shibboleth.idp.profile.saml1;
 
+import org.opensaml.common.SAMLObject;
 import org.opensaml.saml1.core.NameIdentifier;
-import org.opensaml.saml1.core.RequestAbstractType;
 import org.opensaml.saml1.core.ResponseAbstractType;
 import org.opensaml.saml1.core.Status;
 
@@ -16,7 +16,7 @@ import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.Ab
  * @param <ResponseType> type of SAML 1 response
  * @param <ProfileConfigurationType> configuration type for this profile
  */
-public abstract class BaseSAML1ProfileRequestContext<RequestType extends RequestAbstractType, ResponseType extends ResponseAbstractType, ProfileConfigurationType extends AbstractSAML1ProfileConfiguration>
+public abstract class BaseSAML1ProfileRequestContext<RequestType extends SAMLObject, ResponseType extends ResponseAbstractType, ProfileConfigurationType extends AbstractSAML1ProfileConfiguration>
         extends BaseSAMLProfileRequestContext<RequestType, ResponseType, NameIdentifier, ProfileConfigurationType> {
 
     /** The request failure status. */
index dfa4dcf..f589fb5 100644 (file)
@@ -328,18 +328,18 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
             if (log.isDebugEnabled()) {
                 log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
                         + " of SAML request " + requestContext.getInboundSAMLMessageId() + " from relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
             }
             Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
 
             requestContext.setAttributes(principalAttributes);
         } catch (AttributeRequestException e) {
             log.error("Error resolving attributes for SAML request " + requestContext.getInboundSAMLMessageId()
-                    + " from relying party " + requestContext.getPeerEntityId(), e);
+                    + " from relying party " + requestContext.getInboundMessageIssuer(), e);
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null, "Error resolving attributes"));
             throw new ProfileException("Error resolving attributes for SAML request "
                     + requestContext.getInboundSAMLMessageId() + " from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
         }
     }
 
@@ -357,7 +357,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         if (log.isDebugEnabled()) {
             log.debug("Creating attribute statement in response to SAML request "
                     + requestContext.getInboundSAMLMessageId() + " from relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
         AbstractSAML2ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
         SAML2AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
@@ -388,19 +388,19 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         AbstractSAML2ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
         if (profileConfiguration == null) {
             log.error("Unable to resolve principal, no SAML 2 profile configuration for relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.REQUEST_DENIED_URI,
                     "Error resolving principal"));
             throw new ProfileException(
                     "Unable to resolve principal, no SAML 2 profile configuration for relying party "
-                            + requestContext.getPeerEntityId());
+                            + requestContext.getInboundMessageIssuer());
         }
         SAML2AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
 
         if (log.isDebugEnabled()) {
             log.debug("Resolving principal name for subject of SAML request "
                     + requestContext.getInboundSAMLMessageId() + " from relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
 
         try {
@@ -408,12 +408,12 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
             requestContext.setPrincipalName(principal);
         } catch (AttributeRequestException e) {
             log.error("Error resolving attributes for SAML request " + requestContext.getInboundSAMLMessageId()
-                    + " from relying party " + requestContext.getPeerEntityId(), e);
+                    + " from relying party " + requestContext.getInboundMessageIssuer(), e);
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.UNKNOWN_PRINCIPAL_URI,
                     "Error resolving principal"));
             throw new ProfileException("Error resolving attributes for SAML request "
                     + requestContext.getInboundSAMLMessageId() + " from relying party "
-                    + requestContext.getPeerEntityId(), e);
+                    + requestContext.getInboundMessageIssuer(), e);
         }
     }
 
@@ -430,7 +430,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     protected void signAssertion(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
             throws ProfileException {
         if (log.isDebugEnabled()) {
-            log.debug("Determining if SAML assertion to relying party " + requestContext.getPeerEntityId()
+            log.debug("Determining if SAML assertion to relying party " + requestContext.getInboundMessageIssuer()
                     + " should be signed");
         }
 
@@ -443,7 +443,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
             if (ssoDescriptor.getWantAssertionsSigned() != null) {
                 signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
                 if (log.isDebugEnabled()) {
-                    log.debug("Entity metadata for relying party " + requestContext.getPeerEntityId()
+                    log.debug("Entity metadata for relying party " + requestContext.getInboundMessageIssuer()
                             + " indicates to sign assertions: " + signAssertion);
                 }
             }
@@ -460,7 +460,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
 
         if (log.isDebugEnabled()) {
             log.debug("Determining signing credntial for assertion to relying party "
-                    + requestContext.getPeerEntityId());
+                    + requestContext.getInboundMessageIssuer());
         }
         Credential signatureCredential = profileConfig.getSigningCredential();
         if (signatureCredential == null) {
@@ -474,7 +474,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         }
 
         if (log.isDebugEnabled()) {
-            log.debug("Signing assertion to relying party " + requestContext.getPeerEntityId());
+            log.debug("Signing assertion to relying party " + requestContext.getInboundMessageIssuer());
         }
         Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
         
@@ -586,7 +586,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     protected NameID buildNameId(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
         if (log.isDebugEnabled()) {
             log.debug("Building assertion NameID for principal/relying party:" + requestContext.getPrincipalName()
-                    + "/" + requestContext.getPeerEntityId());
+                    + "/" + requestContext.getInboundMessageIssuer());
         }
         Map<String, BaseAttribute> principalAttributes = requestContext.getPrincipalAttributes();
         List<String> supportedNameFormats = getNameFormats(requestContext);
index 4cfc5f5..15b430c 100644 (file)
@@ -82,12 +82,12 @@ public class ArtifactResolution extends AbstractSAML2ProfileHandler {
         try {
             if (requestContext.getRelyingPartyConfiguration() == null) {
                 log.error("SAML 2 Artifact Resolve profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
                 requestContext.setFailureStatus(buildStatus(StatusCode.SUCCESS_URI, StatusCode.REQUEST_DENIED_URI,
                         "SAML 2 Artifact Resolve profile is not configured for relying party "
-                                + requestContext.getPeerEntityId()));
+                                + requestContext.getInboundMessageIssuer()));
                 throw new ProfileException("SAML 2 Artifact Resolve profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
             }
 
             checkSamlVersion(requestContext);
@@ -106,9 +106,9 @@ public class ArtifactResolution extends AbstractSAML2ProfileHandler {
                         "Artifact issuer mismatch."));
             }
 
-            if (!artifactEntry.getRelyingPartyId().equals(requestContext.getPeerEntityId())) {
+            if (!artifactEntry.getRelyingPartyId().equals(requestContext.getInboundMessageIssuer())) {
                 log.error("Artifact requester mismatch.  Artifact was issued to " + artifactEntry.getRelyingPartyId()
-                        + " but was resolve request came from " + requestContext.getPeerEntityId());
+                        + " but was resolve request came from " + requestContext.getInboundMessageIssuer());
                 requestContext.setFailureStatus(buildStatus(StatusCode.SUCCESS_URI, StatusCode.REQUEST_DENIED_URI,
                         "Artifact requester mismatch."));
             }
@@ -179,7 +179,7 @@ public class ArtifactResolution extends AbstractSAML2ProfileHandler {
         } finally {
             // Set as much information as can be retrieved from the decoded message
             try {
-                String relyingPartyId = requestContext.getPeerEntityId();
+                String relyingPartyId = requestContext.getInboundMessageIssuer();
                 RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
                 requestContext.setRelyingPartyConfiguration(rpConfig);
 
index e53c0b0..945eda4 100644 (file)
@@ -58,10 +58,10 @@ public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
         try {
             if (requestContext.getRelyingPartyConfiguration() == null) {
                 log.error("SAML 2 Attribute Query profile is not configured for relying party "
-                        + requestContext.getPeerEntityId());
+                        + requestContext.getInboundMessageIssuer());
                 requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.REQUEST_DENIED_URI,
                         "SAML 2 Attribute Query profile is not configured for relying party "
-                                + requestContext.getPeerEntityId()));
+                                + requestContext.getInboundMessageIssuer()));
                 samlResponse = buildErrorResponse(requestContext);
             }
 
@@ -139,7 +139,7 @@ public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
         } finally {
             // Set as much information as can be retrieved from the decoded message
             try {
-                String relyingPartyId = requestContext.getPeerEntityId();
+                String relyingPartyId = requestContext.getInboundMessageIssuer();
                 RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
                 requestContext.setRelyingPartyConfiguration(rpConfig);
 
index 417438c..3fcf8ce 100644 (file)
@@ -20,7 +20,7 @@
     <!-- Release the Principal as an attribute and encode it as the SAML 1 and 2 name IDs -->
     <resolver:AttributeDefinition id="principalName" xsi:type="PrincipalName" xmlns="urn:mace:shibboleth:2.0:resolver:ad">
         <resolver:AttributeEncoder xsi:type="SAML1StringNameIdentifier" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
-                                   nameFormat="urn:mace:shibboleth:1.0:nameIdentifier" />
+                                   nameFormat="urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified" />
 
         <resolver:AttributeEncoder xsi:type="SAML2StringNameID" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
                                    nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified" />
index ca6e16a..86867de 100644 (file)
@@ -57,6 +57,7 @@
                 <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
                     <NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
                     <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://example.org/mySP" index="0"/>
+                    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://example.org/mySP" index="0"/>
                     <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/mySP" index="0" />
                     <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.org/mySP" index="0" />
                 </SPSSODescriptor>
diff --git a/test/edu/internet2/middleware/shibboleth/idp/system/conf1/SAML1AttributeQueryTestCase.java b/test/edu/internet2/middleware/shibboleth/idp/system/conf1/SAML1AttributeQueryTestCase.java
new file mode 100644 (file)
index 0000000..a83dd7a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed 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 edu.internet2.middleware.shibboleth.idp.system.conf1;
+
+import java.io.StringWriter;
+
+import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.saml1.core.AttributeQuery;
+import org.opensaml.saml1.core.NameIdentifier;
+import org.opensaml.saml1.core.Subject;
+import org.opensaml.ws.soap.common.SOAPObjectBuilder;
+import org.opensaml.ws.soap.soap11.Body;
+import org.opensaml.ws.soap.soap11.Envelope;
+import org.opensaml.ws.transport.http.HTTPInTransport;
+import org.opensaml.ws.transport.http.HTTPOutTransport;
+import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
+import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
+import org.opensaml.xml.io.Marshaller;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.util.XMLHelper;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.w3c.dom.Element;
+
+import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
+
+/**
+ * Unit test for the SAML 1 attribute query flow.
+ */
+public class SAML1AttributeQueryTestCase extends BaseConf1TestCase {
+    
+    /** Tests that the attribute query handler correctly handles an incomming query. */
+    public void testAttributeQuery() throws Exception{
+        AttributeQuery query = buildAttributeQuery("urn:example.org:sp1");
+        String soapMessage = getSOAPMessage(query);
+
+        MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+        servletRequest.setPathInfo("/saml1/SOAP/AttributeQuery");
+        servletRequest.setContent(soapMessage.getBytes());
+
+        MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+
+        ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
+                "shibboleth.HandlerManager");
+        ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+        assertNotNull(handler);
+
+        // Process request
+        HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
+        HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse);
+        handler.processRequest(profileRequest, profileResponse);
+
+        String response = servletResponse.getContentAsString();
+        assertTrue(response.contains("samlp:Success"));
+        assertTrue(response.contains("AttributeName=\"principalName\""));
+        assertTrue(response.contains("testUser"));
+    }
+    
+    /** Tests that the attribute query handler correctly fails out if the profile is not configured. */
+    public void testAuthenticationWithoutConfiguredQuery() throws Exception{
+        AttributeQuery query = buildAttributeQuery("urn:example.org:BogusSP");
+        String soapMessage = getSOAPMessage(query);
+
+        MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+        servletRequest.setPathInfo("/saml1/SOAP/AttributeQuery");
+        servletRequest.setContent(soapMessage.getBytes());
+
+        MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+
+        ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
+                "shibboleth.HandlerManager");
+        ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+        assertNotNull(handler);
+
+        // Process request
+        HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
+        HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse);
+        handler.processRequest(profileRequest, profileResponse);
+            
+        String response = servletResponse.getContentAsString();
+        assertTrue(response.contains("samlp:Responder"));
+        assertTrue(response.contains("samlp:RequestDenied"));
+    }
+
+    /**
+     * Builds a basic attribute query.
+     * 
+     * @param relyingPartyId ID of the relying party that issued the assertion
+     * 
+     * @return basic attribute query
+     */
+    @SuppressWarnings("unchecked")
+    protected AttributeQuery buildAttributeQuery(String relyingPartyId) {
+        SAMLObjectBuilder<NameIdentifier> nameIdBuilder = (SAMLObjectBuilder<NameIdentifier>) builderFactory
+                .getBuilder(NameIdentifier.DEFAULT_ELEMENT_NAME);
+        NameIdentifier nameId = nameIdBuilder.buildObject();
+        nameId.setNameIdentifier("testUser");
+
+        SAMLObjectBuilder<Subject> subjectBuilder = (SAMLObjectBuilder<Subject>) builderFactory
+                .getBuilder(Subject.DEFAULT_ELEMENT_NAME);
+        Subject subject = subjectBuilder.buildObject();
+        subject.setNameIdentifier(nameId);
+
+        SAMLObjectBuilder<AttributeQuery> attributeQueryBuilder = (SAMLObjectBuilder<AttributeQuery>) builderFactory
+                .getBuilder(AttributeQuery.DEFAULT_ELEMENT_NAME);
+        AttributeQuery query = attributeQueryBuilder.buildObject();
+        query.setResource(relyingPartyId);
+        query.setSubject(subject);
+
+        return query;
+    }
+
+    /**
+     * Wraps an attribute query in a SOAP message, marshalls, and serializes it.
+     * 
+     * @param query the attribute query to wrap
+     * 
+     * @return the SOAP message
+     * 
+     * @throws MarshallingException thrown if the message can not be marshalled
+     */
+    @SuppressWarnings("unchecked")
+    protected String getSOAPMessage(AttributeQuery query) throws MarshallingException {
+        SOAPObjectBuilder<Body> bodyBuilder = (SOAPObjectBuilder<Body>) builderFactory
+                .getBuilder(Body.DEFAULT_ELEMENT_NAME);
+        Body body = bodyBuilder.buildObject();
+        body.getUnknownXMLObjects().add(query);
+
+        SOAPObjectBuilder<Envelope> envelopeBuilder = (SOAPObjectBuilder<Envelope>) builderFactory
+                .getBuilder(Envelope.DEFAULT_ELEMENT_NAME);
+        Envelope envelope = envelopeBuilder.buildObject();
+        envelope.setBody(body);
+
+        Marshaller marshaller = marshallerFactory.getMarshaller(envelope);
+        Element envelopeElem = marshaller.marshall(envelope);
+
+        StringWriter writer = new StringWriter();
+        XMLHelper.writeNode(envelopeElem, writer);
+        return writer.toString();
+    }
+}
\ No newline at end of file
index 9b39f14..79a7073 100644 (file)
@@ -61,7 +61,7 @@ public class ShibbolethSSOTestCase extends BaseConf1TestCase {
         assertEquals(false, loginContext.getPassiveAuth());
         assertEquals("/AuthnEngine", loginContext.getAuthenticationEngineURL());
         assertEquals("/shibboleth/SSO", loginContext.getProfileHandlerURL());
-        assertEquals("urn:example.org:sp", loginContext.getRelyingPartyId());
+        assertEquals("urn:example.org:sp1", loginContext.getRelyingPartyId());
         assertEquals(0, loginContext.getRequestedAuthenticationMethods().size());
         assertEquals("https://example.org/mySP", loginContext.getSpAssertionConsumerService());
         assertEquals("https://example.org/mySP", loginContext.getSpTarget());