Renamed AttributeQuery to AbstractAttributeQuery.
authordfisher <dfisher@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 19 Apr 2007 23:49:29 +0000 (23:49 +0000)
committerdfisher <dfisher@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 19 Apr 2007 23:49:29 +0000 (23:49 +0000)
Created HTTPSOAPAttributeQuery.

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

src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AbstractAttributeQuery.java [moved from src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AttributeQuery.java with 60% similarity]
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/HTTPSOAPAttributeQuery.java [new file with mode: 0644]

 
 package edu.internet2.middleware.shibboleth.idp.profile.saml2;
 
-import javax.servlet.ServletException;
-
 import org.apache.log4j.Logger;
-import org.joda.time.DateTime;
 import org.opensaml.common.SAMLObjectBuilder;
-import org.opensaml.common.binding.BindingException;
 import org.opensaml.saml2.core.Advice;
 import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.AttributeStatement;
 import org.opensaml.saml2.core.Audience;
 import org.opensaml.saml2.core.AudienceRestriction;
 import org.opensaml.saml2.core.Conditions;
@@ -36,28 +31,25 @@ import org.opensaml.saml2.core.StatusCode;
 import org.opensaml.saml2.core.Subject;
 import org.opensaml.saml2.encryption.Encrypter;
 import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.xml.XMLObjectBuilder;
 import org.opensaml.xml.encryption.EncryptionException;
-import org.opensaml.xml.security.credential.Credential;
+import org.opensaml.xml.signature.Signature;
+import org.opensaml.xml.signature.Signer;
 
-import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
 import edu.internet2.middleware.shibboleth.common.attribute.SAML2AttributeAuthority;
 import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethAttributeRequestContext;
 import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAML2AttributeAuthority;
 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
-import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
-import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
 import edu.internet2.middleware.shibboleth.common.relyingparty.saml2.AttributeQueryConfiguration;
-import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
 
 /**
  * SAML 2.0 Attribute Query profile handler.
  */
-public class AttributeQuery extends AbstractSAML2ProfileHandler {
+public abstract class AbstractAttributeQuery extends AbstractSAML2ProfileHandler {
 
     /** Class logger. */
-    private static Logger log = Logger.getLogger(AttributeQuery.class);
+    private static Logger log = Logger.getLogger(AbstractAttributeQuery.class);
 
     /** For building response. */
     private SAMLObjectBuilder<Response> responseBuilder;
@@ -89,25 +81,18 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
     /** For building advice. */
     private SAMLObjectBuilder<Advice> adviceBuilder;
 
-    /** Provider id. */
-    private String providerId;
+    /** For building signature. */
+    private XMLObjectBuilder<Signature> signatureBuilder;
 
     /** Attribute authority. */
     private SAML2AttributeAuthority attributeAuthority;
 
-    /** Attribute query configuration. */
-    private AttributeQueryConfiguration config;
-
     /**
      * This creates a new attribute query.
      * 
      * @param ar <code>AttributeResolver</code>
      */
-    public AttributeQuery(AttributeResolver<ShibbolethAttributeRequestContext> ar) {
-        // instantiate configuration
-        config = new AttributeQueryConfiguration();
-        providerId = config.getProfileId();
-
+    public AbstractAttributeQuery(AttributeResolver<ShibbolethAttributeRequestContext> ar) {
         // instantiate attribute authority
         attributeAuthority = new ShibbolethSAML2AttributeAuthority(ar);
 
@@ -116,9 +101,9 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
         statusBuilder = (SAMLObjectBuilder<Status>) getBuilderFactory().getBuilder(Status.DEFAULT_ELEMENT_NAME);
         statusCodeBuilder = (SAMLObjectBuilder<StatusCode>) getBuilderFactory().getBuilder(
                 StatusCode.DEFAULT_ELEMENT_NAME);
+        issuerBuilder = (SAMLObjectBuilder<Issuer>) getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
         assertionBuilder = (SAMLObjectBuilder<Assertion>) getBuilderFactory()
                 .getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
-        issuerBuilder = (SAMLObjectBuilder<Issuer>) getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
         subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(Subject.DEFAULT_ELEMENT_NAME);
         conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory().getBuilder(
                 Conditions.DEFAULT_ELEMENT_NAME);
@@ -126,117 +111,99 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
                 AudienceRestriction.DEFAULT_ELEMENT_NAME);
         audienceBuilder = (SAMLObjectBuilder<Audience>) getBuilderFactory().getBuilder(Audience.DEFAULT_ELEMENT_NAME);
         adviceBuilder = (SAMLObjectBuilder<Advice>) getBuilderFactory().getBuilder(Advice.DEFAULT_ELEMENT_NAME);
+        signatureBuilder = (XMLObjectBuilder<Signature>) getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME);
     }
 
-    /** {@inheritDoc} */
-    public boolean processRequest(ProfileRequest request, ProfileResponse response) throws ServletException {
-        if (log.isDebugEnabled()) {
-            log.debug("begin processRequest");
-        }
-
-        // get message from the decoder
-        org.opensaml.saml2.core.AttributeQuery message = null;
-        try {
-            message = (org.opensaml.saml2.core.AttributeQuery) decodeMessage(request.getMessageDecoder(), request
-                    .getRequest());
-        } catch (BindingException e) {
-            log.error("Error decoding attribute query message", e);
-            throw new ServletException("Error decoding attribute query message");
-        }
-
-        // TODO get user data from the session
-        ServiceInformation serviceInformation = null;
-        String principalName = serviceInformation.getSubjectNameID().getSPProvidedID();
-        String authenticationMethod = serviceInformation.getAuthenticationMethod().getAuthenticationMethod();
-
-        // create attribute request for the attribute authority
-        ShibbolethAttributeRequestContext requestContext = null;
-        try {
-            MetadataProvider metadataProvider = getRelyingPartyManager().getMetadataProvider();
-            RelyingPartyConfiguration relyingPartyConfiguration = getRelyingPartyManager()
-                    .getRelyingPartyConfiguration(providerId);
-            requestContext = new ShibbolethAttributeRequestContext(metadataProvider, relyingPartyConfiguration);
-            requestContext.setPrincipalName(principalName);
-            requestContext.setPrincipalAuthenticationMethod(authenticationMethod);
-            requestContext.setRequest(request.getRequest());
-        } catch (MetadataProviderException e) {
-            log.error("Error creating ShibbolethAttributeRequestContext", e);
-            throw new ServletException("Error retrieving metadata", e);
-        }
-
-        // resolve attributes with the attribute authority
-        AttributeStatement statement = null;
-        try {
-            statement = attributeAuthority.performAttributeQuery(requestContext);
-        } catch (AttributeRequestException e) {
-            log.error("Error resolving attributes", e);
-            throw new ServletException("Error resolving attributes", e);
-        }
+    /**
+     * This returns the <code>RelyingPartyConfiguration</code> for the supplied provider id.
+     * 
+     * @param providerId <code>String</code>
+     * @return <code>RelyingPartyConfiguration</code>
+     */
+    protected RelyingPartyConfiguration getRelyingPartyConfiguration(String providerId) {
+        return getRelyingPartyConfigurationManager().getRelyingPartyConfiguration(providerId);
+    }
 
-        // construct attribute response
-        Response samlResponse = null;
-        try {
-            ProfileResponseContext profileResponse = new ProfileResponseContext(request, message);
-            profileResponse.setAttributeStatement(statement);
-            samlResponse = buildResponse(profileResponse);
-        } catch (EncryptionException e) {
-            log.error("Error encrypting SAML response", e);
-            throw new ServletException("Error encrypting SAML response", e);
-        }
-        if (log.isDebugEnabled()) {
-            log.debug("built saml2 response: " + samlResponse);
-        }
+    /**
+     * This returns the <code>AttributeQueryConfiguration</code> for the supplied provider id.
+     * 
+     * @param providerId <code>String</code>
+     * @return <code>AttributeQueryConfiguration</code>
+     */
+    protected AttributeQueryConfiguration getAttributeQueryConfiguration(String providerId) {
+        return (AttributeQueryConfiguration) getRelyingPartyConfiguration(providerId).getProfileConfigurations().get(
+                AttributeQueryConfiguration.PROFILE_ID);
+    }
 
-        // encode response
-        try {
-            encodeResponse(response.getMessageEncoder(), samlResponse);
-        } catch (BindingException e) {
-            log.error("Error encoding attribute query response", e);
-            throw new ServletException("Error encoding attribute query response", e);
-        }
+    /**
+     * This returns the <code>MetadataProvider</code> for this attribute query.
+     * 
+     * @return <code>MetadataProvider</code>
+     */
+    protected MetadataProvider getMetadataProvider() {
+        return getRelyingPartyConfigurationManager().getMetadataProvider();
+    }
 
-        return true;
+    /**
+     * This returns the <code>AttributeAuthority</code> for this attribute query.
+     * 
+     * @return <code>SAML2AttributeAuthority</code>
+     */
+    protected SAML2AttributeAuthority getAttributeAuthority() {
+        return attributeAuthority;
     }
 
     /**
      * This builds the response for this SAML request.
      * 
      * @param responseContext <code>ProfileResponseContext</code>
+     * @param issuer <code>String</code>
+     * @param destination <code>String</code>
      * @return <code>Response</code>
      * @throws EncryptionException if an error occurs attempting to encrypt data
      */
-    private Response buildResponse(ProfileResponseContext responseContext) throws EncryptionException {
+    protected Response buildResponse(ProfileResponseContext responseContext, String issuer, String destination)
+            throws EncryptionException {
+        AttributeQueryConfiguration config = getAttributeQueryConfiguration(responseContext.getProviderId());
+
         /*
          * required: samlp:Status, ID, Version, IssueInstant
          */
         Response response = responseBuilder.buildObject();
         response.setVersion(SAML_VERSION);
         response.setID(getIdGenerator().generateIdentifier());
-        response.setInResponseTo(responseContext.getRequest().getMessageDecoder().getSecurityPolicy().getIssuer()
-                .toString());
+        response.setInResponseTo(issuer);
         response.setIssueInstant(responseContext.getIssueInstant());
-        response.setDestination(responseContext.getRequest().getRequest().getRemoteHost());
+        response.setDestination(destination);
 
-        response.setIssuer(buildIssuer());
+        response.setIssuer(buildIssuer(responseContext.getProviderId()));
 
-        // TODO get consent configuration
         /*
-         * if (consent != null) { response.setConsent(consent); }
+         * Will be hard coded in the future: if (consent != null) { response.setConsent(consent); }
+         * 
          */
 
-        // TODO get extension configuration
         /*
-         * if (extensions != null) { response.setExtensions(extensions); }
+         * No extensions currently exist, will be hardcorded in the future: if (extensions != null) {
+         * response.setExtensions(extensions); }
+         * 
          */
 
         if (config.getSignAssertions()) {
-            // TODO sign assertion: Credential credential = config.getSigningCredential();
+            Signature s = buildSignature();
+            s.setSigningKey(config.getSigningCredential().getPrivateKey());
             if (config.getEncryptAssertion()) {
                 // TODO load encryption parameters
                 Encrypter encrypter = null;
-                response.getEncryptedAssertions().add(encrypter.encrypt(buildAssertion(responseContext)));
+                Assertion a = buildAssertion(responseContext);
+                a.setSignature(s);
+                Signer.signObject(s);
+                response.getEncryptedAssertions().add(encrypter.encrypt(a));
             } else {
-                response.getAssertions().add(buildAssertion(responseContext));
+                Assertion a = buildAssertion(responseContext);
+                a.setSignature(s);
+                Signer.signObject(s);
+                response.getAssertions().add(a);
             }
         } else {
             if (config.getEncryptAssertion()) {
@@ -273,6 +240,8 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
      * @throws EncryptionException if an error occurs attempting to encrypt data
      */
     private Assertion buildAssertion(ProfileResponseContext responseContext) throws EncryptionException {
+        AttributeQueryConfiguration config = getAttributeQueryConfiguration(responseContext.getProviderId());
+
         /*
          * required: saml:Issuer, ID, Version, IssueInstant
          */
@@ -280,12 +249,12 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
         assertion.setID(getIdGenerator().generateIdentifier());
         assertion.setIssueInstant(responseContext.getIssueInstant());
         assertion.setVersion(SAML_VERSION);
-        assertion.setIssuer(buildIssuer());
+        assertion.setIssuer(buildIssuer(responseContext.getProviderId()));
 
         // build subject
-        assertion.setSubject(buildSubject(responseContext.getMessage().getSubject()));
+        assertion.setSubject(buildSubject(responseContext.getMessage().getSubject(), config.getEncryptNameID()));
         // build conditions
-        assertion.setConditions(buildConditions(responseContext.getIssueInstant()));
+        assertion.setConditions(buildConditions(responseContext));
         // build advice
         assertion.setAdvice(buildAdvice());
         // add attribute statement
@@ -296,13 +265,13 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
     /**
      * This builds the issuer response for this SAML request.
      * 
+     * @param providerId <code>String</code>
      * @return <code>Issuer</code>
      */
-    private Issuer buildIssuer() {
-        RelyingPartyConfiguration relyingPartyConfiguration = getRelyingPartyManager().getRelyingPartyConfiguration(
-                providerId);
+    private Issuer buildIssuer(String providerId) {
+        RelyingPartyConfiguration relyingPartyConfiguration = getRelyingPartyConfiguration(providerId);
         Issuer issuer = issuerBuilder.buildObject();
-        issuer.setValue(relyingPartyConfiguration.getProviderID());
+        issuer.setValue(relyingPartyConfiguration.getProviderId());
         return issuer;
     }
 
@@ -310,12 +279,13 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
      * This builds the subject for this SAML request.
      * 
      * @param messageSubject <code>Subject</code>
+     * @param encryptNameId <code>boolean</code>
      * @return <code>Subject</code>
      * @throws EncryptionException if encryption of the name id fails
      */
-    private Subject buildSubject(Subject messageSubject) throws EncryptionException {
+    private Subject buildSubject(Subject messageSubject, boolean encryptNameId) throws EncryptionException {
         Subject subject = subjectBuilder.buildObject();
-        if (config.getEncryptNameID()) {
+        if (encryptNameId) {
             // TODO load encryption parameters
             Encrypter encrypter = null;
             subject.setEncryptedID(encrypter.encrypt(messageSubject.getNameID()));
@@ -329,13 +299,15 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
     /**
      * This builds the conditions for this SAML request.
      * 
-     * @param issueInstant <code>DateTime</code>
+     * @param responseContext <code>ProfileResponseContext</code>
      * @return <code>Conditions</code>
      */
-    private Conditions buildConditions(DateTime issueInstant) {
+    private Conditions buildConditions(ProfileResponseContext responseContext) {
+        AttributeQueryConfiguration config = getAttributeQueryConfiguration(responseContext.getProviderId());
+
         Conditions conditions = conditionsBuilder.buildObject();
-        conditions.setNotBefore(issueInstant);
-        conditions.setNotOnOrAfter(issueInstant.plus(config.getAssertionLifetime()));
+        conditions.setNotBefore(responseContext.getIssueInstant());
+        conditions.setNotOnOrAfter(responseContext.getIssueInstant().plus(config.getAssertionLifetime()));
 
         // add audience restrictions
         AudienceRestriction audienceRestriction = audienceRestrictionBuilder.buildObject();
@@ -355,8 +327,10 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
         }
         proxyRestriction.setProxyCount(new Integer(config.getProxyCount()));
 
-        // TODO add additional conditions : conditions.getConditions().add(Condition);
-        // TODO what about OneTimeUse?
+        /*
+         * OneTimeUse and additional conditions not supported yet
+         */
+
         return conditions;
     }
 
@@ -366,13 +340,20 @@ public class AttributeQuery extends AbstractSAML2ProfileHandler {
      * @return <code>Advice</code>
      */
     private Advice buildAdvice() {
+        /*
+         * Advice not supported at this time
+         */
         Advice advice = adviceBuilder.buildObject();
-        // TODO set advice
-        // advice.getAssertionIDReferences().add();
-        // advice.getAssertionURIReferences().add();
-        // advice.getAssertions().add();
-        // advice.getEncryptedAssertions().add();
-        // advice.addNamespace(namespace);
         return advice;
     }
+
+    /**
+     * This builds a signature for this SAML request.
+     * 
+     * @return <code>Signature</code>
+     */
+    private Signature buildSignature() {
+        Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
+        return signature;
+    }
 }
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/idp/profile/saml2/HTTPSOAPAttributeQuery.java b/src/edu/internet2/middleware/shibboleth/idp/profile/saml2/HTTPSOAPAttributeQuery.java
new file mode 100644 (file)
index 0000000..b625dca
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.profile.saml2;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.opensaml.common.binding.BindingException;
+import org.opensaml.saml2.binding.HTTPSOAP11Decoder;
+import org.opensaml.saml2.binding.HTTPSOAP11Encoder;
+import org.opensaml.saml2.core.AttributeStatement;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.xml.encryption.EncryptionException;
+
+import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
+import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethAttributeRequestContext;
+import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
+import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
+
+/**
+ * SAML 2.0 SOAP Attribute Query profile handler.
+ */
+public class HTTPSOAPAttributeQuery extends AbstractAttributeQuery {
+
+    /** Class logger. */
+    private static Logger log = Logger.getLogger(HTTPSOAPAttributeQuery.class);
+
+    /**
+     * This creates a new http soap attribute query.
+     * 
+     * @param ar <code>AttributeResolver</code>
+     */
+    public HTTPSOAPAttributeQuery(AttributeResolver<ShibbolethAttributeRequestContext> ar) {
+        super(ar);
+    }
+
+    /** {@inheritDoc} */
+    public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
+            throws ProfileException {
+        if (log.isDebugEnabled()) {
+            log.debug("begin processRequest");
+        }
+
+        // check that request/response is of proper type
+        if (!(request.getRawRequest() instanceof HttpServletRequest)) {
+            throw new ProfileException(HTTPSOAPAttributeQuery.class.getName() + " can only process requests of type "
+                    + HttpServletRequest.class.getName());
+        } else if (!(response.getRawResponse() instanceof HttpServletResponse)) {
+            throw new ProfileException(HTTPSOAPAttributeQuery.class.getName() + " can only process responses of type "
+                    + HttpServletResponse.class.getName());
+        }
+
+        // create decoder
+        HTTPSOAP11Decoder decoder = new HTTPSOAP11Decoder();
+        decoder.setMetadataProvider(getMetadataProvider());
+        // TODO decoder.setSecurityPolicy(policy);
+        // TODO decoder.setTrustEngine(newEngine);
+
+        // get message from the decoder
+        org.opensaml.saml2.core.AttributeQuery message = null;
+        try {
+            decoder.setRequest((HttpServletRequest) request.getRawRequest());
+            decoder.decode();
+            if (log.isDebugEnabled()) {
+                log.debug("decoded http servlet request");
+            }
+            message = (org.opensaml.saml2.core.AttributeQuery) decoder.getSAMLMessage();
+        } catch (BindingException e) {
+            log.error("Error decoding attribute query message", e);
+            throw new ProfileException("Error decoding attribute query message");
+        }
+
+        // get the provider id from the message issuer
+        String providerId = message.getIssuer().getSPProvidedID();
+
+        // TODO get user data from the session, need sessionId
+        // ?? getSessionManager().getSession(null).getServicesInformation().get(0);
+        ServiceInformation serviceInformation = null;
+        String principalName = serviceInformation.getSubjectNameID().getSPProvidedID();
+        String authenticationMethod = serviceInformation.getAuthenticationMethod().getAuthenticationMethod();
+
+        // create attribute request for the attribute authority
+        ShibbolethAttributeRequestContext requestContext = null;
+        try {
+            requestContext = new ShibbolethAttributeRequestContext(getMetadataProvider(),
+                    getRelyingPartyConfiguration(providerId));
+            requestContext.setPrincipalName(principalName);
+            requestContext.setPrincipalAuthenticationMethod(authenticationMethod);
+            requestContext.setRequest(request.getRawRequest());
+        } catch (MetadataProviderException e) {
+            log.error("Error creating ShibbolethAttributeRequestContext", e);
+            throw new ProfileException("Error retrieving metadata", e);
+        }
+
+        // resolve attributes with the attribute authority
+        AttributeStatement statement = null;
+        try {
+            statement = getAttributeAuthority().performAttributeQuery(requestContext);
+        } catch (AttributeRequestException e) {
+            log.error("Error resolving attributes", e);
+            throw new ProfileException("Error resolving attributes", e);
+        }
+
+        // construct attribute response
+        Response samlResponse = null;
+        try {
+            ProfileResponseContext profileResponse = new ProfileResponseContext(request, message);
+            profileResponse.setAttributeStatement(statement);
+            samlResponse = buildResponse(profileResponse, decoder.getSecurityPolicy().getIssuer().toString(), request
+                    .getRawRequest().getRemoteHost());
+        } catch (EncryptionException e) {
+            log.error("Error encrypting SAML response", e);
+            throw new ProfileException("Error encrypting SAML response", e);
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("built saml2 response: " + samlResponse);
+        }
+
+        // encode response
+        try {
+            HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
+            encoder.setMetadataProvider(getMetadataProvider());
+            encoder.setRelyingParty(getRelyingPartyConfiguration(providerId).getRelyingPartyId());
+            encoder.setResponse((HttpServletResponse) response.getRawResponse());
+            encoder.setSAMLMessage(samlResponse);
+            encoder.encode();
+        } catch (BindingException e) {
+            log.error("Error encoding attribute query response", e);
+            throw new ProfileException("Error encoding attribute query response", e);
+        }
+    }
+}