Deal with selecting relying party endpoint sooner and populating subject confirmation...
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 11 Jul 2007 13:16:37 +0000 (13:16 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 11 Jul 2007 13:16:37 +0000 (13:16 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2305 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/profile/AbstractSAMLProfileHandler.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

index f6a712d..643cbf7 100644 (file)
@@ -25,6 +25,7 @@ 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.common.SAMLObject;
 import org.opensaml.common.binding.decoding.MessageDecoderFactory;
 import org.opensaml.common.binding.encoding.MessageEncoderFactory;
+import org.opensaml.saml2.metadata.Endpoint;
 import org.opensaml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.provider.MetadataProvider;
 import org.opensaml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.provider.MetadataProvider;
@@ -158,13 +159,16 @@ public abstract class AbstractSAMLProfileHandler extends
      * @param <StatusType> type of Status object
      */
     protected class SAMLProfileRequestContext<StatusType extends SAMLObject> extends ShibbolethProfileRequestContext {
      * @param <StatusType> type of Status object
      */
     protected class SAMLProfileRequestContext<StatusType extends SAMLObject> extends ShibbolethProfileRequestContext {
-
+        
         /** Entity descriptor for the asserting party. */
         private EntityDescriptor assertingPartyMetadata;
 
         /** Role descriptor meatadata for the asserting party. */
         private RoleDescriptor assertingPartyRoleMetadata;
 
         /** Entity descriptor for the asserting party. */
         private EntityDescriptor assertingPartyMetadata;
 
         /** Role descriptor meatadata for the asserting party. */
         private RoleDescriptor assertingPartyRoleMetadata;
 
+        /** Endpoint of relying party. */
+        private Endpoint relyingPartyEndpoint;
+        
         /** Entity descriptor for the relying party. */
         private EntityDescriptor relyingPartyMetadata;
 
         /** Entity descriptor for the relying party. */
         private EntityDescriptor relyingPartyMetadata;
 
@@ -217,6 +221,24 @@ public abstract class AbstractSAMLProfileHandler extends
         public void setAssertingPartyRoleMetadata(RoleDescriptor descriptor) {
             assertingPartyRoleMetadata = descriptor;
         }
         public void setAssertingPartyRoleMetadata(RoleDescriptor descriptor) {
             assertingPartyRoleMetadata = descriptor;
         }
+        
+        /**
+         * Gets the endpoint for the relying party.
+         * 
+         * @return endpoint for the relying party
+         */
+        public Endpoint getRelyingPartyEndpoint(){
+            return relyingPartyEndpoint;
+        }
+        
+        /**
+         * Sets the endpoint for the relying party.
+         * 
+         * @param endpoint endpoint for the relying party
+         */
+        public void setRelyingPartyEndpoint(Endpoint endpoint){
+            relyingPartyEndpoint = endpoint;
+        }
 
         /**
          * Gets the metadata for the relying party.
 
         /**
          * Gets the metadata for the relying party.
index bfdcfdc..bd08bad 100644 (file)
@@ -49,8 +49,10 @@ import org.opensaml.saml2.core.StatusMessage;
 import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.core.SubjectConfirmation;
 import org.opensaml.saml2.core.StatusResponseType;
 import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.core.SubjectConfirmation;
+import org.opensaml.saml2.core.SubjectConfirmationData;
 import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
 import org.opensaml.saml2.metadata.AuthnAuthorityDescriptor;
 import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
 import org.opensaml.saml2.metadata.AuthnAuthorityDescriptor;
+import org.opensaml.saml2.metadata.Endpoint;
 import org.opensaml.saml2.metadata.NameIDFormat;
 import org.opensaml.saml2.metadata.PDPDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml2.metadata.NameIDFormat;
 import org.opensaml.saml2.metadata.PDPDescriptor;
 import org.opensaml.saml2.metadata.RoleDescriptor;
@@ -108,9 +110,12 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     /** For building subject. */
     private SAMLObjectBuilder<Subject> subjectBuilder;
 
     /** For building subject. */
     private SAMLObjectBuilder<Subject> subjectBuilder;
 
-    /** For builder subject confirmation. */
+    /** For building subject confirmation. */
     private SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder;
 
     private SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder;
 
+    /** For building subject confirmation data. */
+    private SAMLObjectBuilder<SubjectConfirmationData> subjectConfirmationDataBuilder;
+
     /** For building conditions. */
     private SAMLObjectBuilder<Conditions> conditionsBuilder;
 
     /** For building conditions. */
     private SAMLObjectBuilder<Conditions> conditionsBuilder;
 
@@ -143,6 +148,8 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(Subject.DEFAULT_ELEMENT_NAME);
         subjectConfirmationBuilder = (SAMLObjectBuilder<SubjectConfirmation>) getBuilderFactory().getBuilder(
                 SubjectConfirmation.DEFAULT_ELEMENT_NAME);
         subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(Subject.DEFAULT_ELEMENT_NAME);
         subjectConfirmationBuilder = (SAMLObjectBuilder<SubjectConfirmation>) getBuilderFactory().getBuilder(
                 SubjectConfirmation.DEFAULT_ELEMENT_NAME);
+        subjectConfirmationDataBuilder = (SAMLObjectBuilder<SubjectConfirmationData>) getBuilderFactory().getBuilder(
+                SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
         conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory().getBuilder(
                 Conditions.DEFAULT_ELEMENT_NAME);
         audienceRestrictionBuilder = (SAMLObjectBuilder<AudienceRestriction>) getBuilderFactory().getBuilder(
         conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory().getBuilder(
                 Conditions.DEFAULT_ELEMENT_NAME);
         audienceRestrictionBuilder = (SAMLObjectBuilder<AudienceRestriction>) getBuilderFactory().getBuilder(
@@ -177,21 +184,23 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * Builds a response to the attribute query within the request context.
      * 
      * @param requestContext current request context
      * Builds a response to the attribute query within the request context.
      * 
      * @param requestContext current request context
-     * @param assertionSubject subject of the assertion within the response
+     * @param subjectConfirmationMethod confirmation method used for the subject
      * @param statements the statements to include in the response
      * 
      * @return the built response
      * 
      * @throws ProfileException thrown if there is a problem creating the SAML response
      */
      * @param statements the statements to include in the response
      * 
      * @return the built response
      * 
      * @throws ProfileException thrown if there is a problem creating the SAML response
      */
-    protected Response buildResponse(SAML2ProfileRequestContext requestContext, Subject assertionSubject,
+    protected Response buildResponse(SAML2ProfileRequestContext requestContext, String subjectConfirmationMethod,
             List<Statement> statements) throws ProfileException {
 
         DateTime issueInstant = new DateTime();
 
             List<Statement> statements) throws ProfileException {
 
         DateTime issueInstant = new DateTime();
 
+        Subject subject = buildSubject(requestContext, subjectConfirmationMethod, issueInstant);
+
         // create the assertion and add the attribute statement
         Assertion assertion = buildAssertion(requestContext, issueInstant);
         // create the assertion and add the attribute statement
         Assertion assertion = buildAssertion(requestContext, issueInstant);
-        assertion.setSubject(assertionSubject);
+        assertion.setSubject(subject);
         if (statements != null) {
             assertion.getStatements().addAll(statements);
         }
         if (statements != null) {
             assertion.getStatements().addAll(statements);
         }
@@ -410,10 +419,10 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
 
         ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery> queryContext;
 
 
         ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery> queryContext;
 
-        if(requestContext.getSamlRequest() instanceof AttributeQuery){
-        queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
-                requestContext.getRelyingPartyConfiguration(), (AttributeQuery) requestContext.getSamlRequest());
-        }else{
+        if (requestContext.getSamlRequest() instanceof AttributeQuery) {
+            queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
+                    requestContext.getRelyingPartyConfiguration(), (AttributeQuery) requestContext.getSamlRequest());
+        } else {
             queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
                     requestContext.getRelyingPartyConfiguration(), null);
         }
             queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
                     requestContext.getRelyingPartyConfiguration(), null);
         }
@@ -542,20 +551,37 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * 
      * @param requestContext current request context
      * @param confirmationMethod subject confirmation method used for the subject
      * 
      * @param requestContext current request context
      * @param confirmationMethod subject confirmation method used for the subject
+     * @param issueInstant instant the subject confirmation data should reflect for issuance
      * 
      * @return SAML subject for the user for the service provider
      * 
      * @throws ProfileException thrown if a NameID can not be created either because there was a problem encoding the
      *             name ID attribute or because there are no supported name formats
      */
      * 
      * @return SAML subject for the user for the service provider
      * 
      * @throws ProfileException thrown if a NameID can not be created either because there was a problem encoding the
      *             name ID attribute or because there are no supported name formats
      */
-    protected Subject buildSubject(SAML2ProfileRequestContext requestContext, String confirmationMethod)
-            throws ProfileException {
+    protected Subject buildSubject(SAML2ProfileRequestContext requestContext, String confirmationMethod,
+            DateTime issueInstant) throws ProfileException {
         NameID nameID = buildNameId(requestContext);
         requestContext.setSubjectNameID(nameID);
         // TODO handle encryption
 
         NameID nameID = buildNameId(requestContext);
         requestContext.setSubjectNameID(nameID);
         // TODO handle encryption
 
+        SubjectConfirmationData confirmationData = subjectConfirmationDataBuilder.buildObject();
+        confirmationData.setAddress(requestContext.getProfileRequest().getRawRequest().getRemoteAddr());
+        confirmationData.setInResponseTo(requestContext.getSamlRequest().getID());
+        confirmationData.setNotOnOrAfter(issueInstant.plus(requestContext.getProfileConfiguration()
+                .getAssertionLifetime()));
+
+        Endpoint relyingPartyEndpoint = requestContext.getRelyingPartyEndpoint();
+        if (relyingPartyEndpoint != null) {
+            if (relyingPartyEndpoint.getResponseLocation() != null) {
+                confirmationData.setRecipient(relyingPartyEndpoint.getResponseLocation());
+            } else {
+                confirmationData.setRecipient(relyingPartyEndpoint.getLocation());
+            }
+        }
+
         SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
         subjectConfirmation.setMethod(confirmationMethod);
         SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
         subjectConfirmation.setMethod(confirmationMethod);
+        subjectConfirmation.setSubjectConfirmationData(confirmationData);
 
         Subject subject = subjectBuilder.buildObject();
         subject.setNameID(nameID);
 
         Subject subject = subjectBuilder.buildObject();
         subject.setNameID(nameID);
@@ -591,7 +617,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         }
 
         if (principalAttributes == null || supportedNameFormats == null) {
         }
 
         if (principalAttributes == null || supportedNameFormats == null) {
-            log.error("No attributes for principal " + requestContext.getPrincipalName() 
+            log.error("No attributes for principal " + requestContext.getPrincipalName()
                     + " support constructions of NameID");
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.INVALID_NAMEID_POLICY_URI,
                     "Unable to construct NameID"));
                     + " support constructions of NameID");
             requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.INVALID_NAMEID_POLICY_URI,
                     "Unable to construct NameID"));
@@ -730,7 +756,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         auditLogEntry.setRequestId(context.getSamlRequest().getID());
         auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
         auditLogEntry.setResponseId(context.getSamlResponse().getID());
         auditLogEntry.setRequestId(context.getSamlRequest().getID());
         auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
         auditLogEntry.setResponseId(context.getSamlResponse().getID());
-        if(context.getPrincipalAttributes() != null){
+        if (context.getPrincipalAttributes() != null) {
             auditLogEntry.getReleasedAttributes().addAll(context.getPrincipalAttributes().keySet());
         }
         getAduitLog().log(Level.CRITICAL, auditLogEntry);
             auditLogEntry.getReleasedAttributes().addAll(context.getPrincipalAttributes().keySet());
         }
         getAduitLog().log(Level.CRITICAL, auditLogEntry);
index 74b6dc2..39de7f1 100644 (file)
@@ -32,7 +32,6 @@ 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.Response;
 import org.opensaml.saml2.core.Statement;
 import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.ws.security.SecurityPolicyException;
 
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.ws.security.SecurityPolicyException;
 
@@ -84,11 +83,8 @@ public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
             ArrayList<Statement> statements = new ArrayList<Statement>();
             statements.add(buildAttributeStatement(requestContext));
 
             ArrayList<Statement> statements = new ArrayList<Statement>();
             statements.add(buildAttributeStatement(requestContext));
 
-            // create the assertion subject
-            Subject assertionSubject = buildSubject(requestContext, "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches");
-
             // create the SAML response
             // create the SAML response
-            samlResponse = buildResponse(requestContext, assertionSubject, statements);
+            samlResponse = buildResponse(requestContext, "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches", statements);
         } catch (ProfileException e) {
             samlResponse = buildErrorResponse(requestContext);
         }
         } catch (ProfileException e) {
             samlResponse = buildErrorResponse(requestContext);
         }
index b10d28a..9dcea39 100644 (file)
@@ -36,6 +36,7 @@ import org.opensaml.common.binding.security.SAMLSecurityPolicy;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.SubjectLocality;
 import org.opensaml.saml2.binding.AuthnResponseEndpointSelector;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.SubjectLocality;
 import org.opensaml.saml2.binding.AuthnResponseEndpointSelector;
+import org.opensaml.saml2.core.AttributeStatement;
 import org.opensaml.saml2.core.AuthnContext;
 import org.opensaml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml2.core.AuthnContextDeclRef;
 import org.opensaml.saml2.core.AuthnContext;
 import org.opensaml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml2.core.AuthnContextDeclRef;
@@ -226,15 +227,15 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
                 throw new ProfileException("User failed authentication");
             }
 
                 throw new ProfileException("User failed authentication");
             }
 
+            AuthnStatement authnStatement = buildAuthnStatement(requestContext);
+            AttributeStatement attributeStatement = buildAttributeStatement(requestContext);
+            
             ArrayList<Statement> statements = new ArrayList<Statement>();
             ArrayList<Statement> statements = new ArrayList<Statement>();
-            statements.add(buildAuthnStatement(requestContext));
-            if (requestContext.getProfileConfiguration().includeAttributeStatement()) {
-                statements.add(buildAttributeStatement(requestContext));
-            }
-
-            Subject assertionSubject = buildSubject(requestContext, "urn:oasis:names:tc:SAML:2.0:cm:bearer");
+            statements.add(authnStatement);
+            //TODO optional include this
+            statements.add(attributeStatement);
 
 
-            samlResponse = buildResponse(requestContext, assertionSubject, statements);
+            samlResponse = buildResponse(requestContext, "urn:oasis:names:tc:SAML:2.0:cm:bearer", statements);
         } catch (ProfileException e) {
             samlResponse = buildErrorResponse(requestContext);
         }
         } catch (ProfileException e) {
             samlResponse = buildErrorResponse(requestContext);
         }
@@ -322,6 +323,8 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
                     .getProfileConfiguration(SSOConfiguration.PROFILE_ID));
 
             requestContext.setSamlRequest(authnRequest);
                     .getProfileConfiguration(SSOConfiguration.PROFILE_ID));
 
             requestContext.setSamlRequest(authnRequest);
+            
+            selectEndpoint(requestContext);
 
             return requestContext;
         } catch (UnmarshallingException e) {
 
             return requestContext;
         } catch (UnmarshallingException e) {
@@ -422,6 +425,22 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
 
         return subjectLocality;
     }
 
         return subjectLocality;
     }
+    
+    /**
+     * Selects the appropriate endpoint for the relying party and stores it in the request context.
+     * 
+     * @param requestContext current request context
+     */
+    protected void selectEndpoint(SSORequestContext requestContext){
+        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(supportedOutgoingBindings);
+        requestContext.setRelyingPartyEndpoint(endpointSelector.selectEndpoint());
+    }
 
     /**
      * Encodes the request's SAML response and writes it to the servlet response.
 
     /**
      * Encodes the request's SAML response and writes it to the servlet response.
@@ -435,15 +454,8 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
             log.debug("Encoding response to SAML request " + requestContext.getSamlRequest().getID()
                     + " from relying party " + requestContext.getRelyingPartyId());
         }
             log.debug("Encoding response to SAML request " + requestContext.getSamlRequest().getID()
                     + " from relying party " + requestContext.getRelyingPartyId());
         }
-        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(supportedOutgoingBindings);
-        Endpoint relyingPartyEndpoint = endpointSelector.selectEndpoint();
 
 
+        Endpoint relyingPartyEndpoint = requestContext.getRelyingPartyEndpoint();
         MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(
                 relyingPartyEndpoint.getBinding());
         if (encoder == null) {
         MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(
                 relyingPartyEndpoint.getBinding());
         if (encoder == null) {