af0b0d94f5f598835bb947c072df0991bba07b69
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / saml2 / HTTPSOAPAttributeQuery.java
1 /*
2  * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.idp.profile.saml2;
18
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.log4j.Logger;
25 import org.opensaml.common.binding.BindingException;
26 import org.opensaml.saml2.binding.HTTPSOAP11Decoder;
27 import org.opensaml.saml2.binding.HTTPSOAP11Encoder;
28 import org.opensaml.saml2.core.AttributeStatement;
29 import org.opensaml.saml2.core.Response;
30 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
31 import org.opensaml.xml.encryption.EncryptionException;
32
33 import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
34 import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethAttributeRequestContext;
35 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
36 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
37 import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
38 import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
39 import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
40
41 /**
42  * SAML 2.0 SOAP Attribute Query profile handler.
43  */
44 public class HTTPSOAPAttributeQuery extends AbstractAttributeQuery {
45
46     /** Class logger. */
47     private static Logger log = Logger.getLogger(HTTPSOAPAttributeQuery.class);
48
49     /**
50      * This creates a new http soap attribute query.
51      * 
52      * @param ar <code>AttributeResolver</code>
53      */
54     public HTTPSOAPAttributeQuery(AttributeResolver<ShibbolethAttributeRequestContext> ar) {
55         super(ar);
56     }
57
58     /** {@inheritDoc} */
59     public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
60             throws ProfileException {
61         if (log.isDebugEnabled()) {
62             log.debug("begin processRequest");
63         }
64
65         // check that request/response is of proper type
66         if (!(request.getRawRequest() instanceof HttpServletRequest)) {
67             throw new ProfileException(HTTPSOAPAttributeQuery.class.getName() + " can only process requests of type "
68                     + HttpServletRequest.class.getName());
69         } else if (!(response.getRawResponse() instanceof HttpServletResponse)) {
70             throw new ProfileException(HTTPSOAPAttributeQuery.class.getName() + " can only process responses of type "
71                     + HttpServletResponse.class.getName());
72         }
73
74         // create decoder
75         HTTPSOAP11Decoder decoder = new HTTPSOAP11Decoder();
76         decoder.setMetadataProvider(getMetadataProvider());
77         // TODO decoder.setSecurityPolicy(policy);
78         // TODO decoder.setTrustEngine(newEngine);
79
80         // get message from the decoder
81         org.opensaml.saml2.core.AttributeQuery message = null;
82         try {
83             decoder.setRequest((HttpServletRequest) request.getRawRequest());
84             decoder.decode();
85             if (log.isDebugEnabled()) {
86                 log.debug("decoded http servlet request");
87             }
88             message = (org.opensaml.saml2.core.AttributeQuery) decoder.getSAMLMessage();
89         } catch (BindingException e) {
90             log.error("Error decoding attribute query message", e);
91             throw new ProfileException("Error decoding attribute query message");
92         }
93
94         // get the provider id from the message issuer
95         String providerId = message.getIssuer().getSPProvidedID();
96
97         // TODO get user data from the session, need sessionId
98         // ?? getSessionManager().getSession(null).getServicesInformation().get(0);
99         ServiceInformation serviceInformation = null;
100         String principalName = serviceInformation.getSubjectNameID().getSPProvidedID();
101         String authenticationMethod = serviceInformation.getAuthenticationMethod().getAuthenticationMethod();
102
103         // create attribute request for the attribute authority
104         ShibbolethAttributeRequestContext requestContext = null;
105         try {
106             requestContext = new ShibbolethAttributeRequestContext(getMetadataProvider(),
107                     getRelyingPartyConfiguration(providerId));
108             requestContext.setPrincipalName(principalName);
109             requestContext.setPrincipalAuthenticationMethod(authenticationMethod);
110             requestContext.setRequest(request.getRawRequest());
111         } catch (MetadataProviderException e) {
112             log.error("Error creating ShibbolethAttributeRequestContext", e);
113             throw new ProfileException("Error retrieving metadata", e);
114         }
115
116         // resolve attributes with the attribute authority
117         AttributeStatement statement = null;
118         try {
119             statement = getAttributeAuthority().performAttributeQuery(requestContext);
120         } catch (AttributeRequestException e) {
121             log.error("Error resolving attributes", e);
122             throw new ProfileException("Error resolving attributes", e);
123         }
124
125         // construct attribute response
126         Response samlResponse = null;
127         try {
128             ProfileResponseContext profileResponse = new ProfileResponseContext(request, message);
129             profileResponse.setIssuer(decoder.getSecurityPolicy().getIssuer().toString());
130             profileResponse.setDestination(request.getRawRequest().getRemoteHost());
131             profileResponse.setAttributeStatement(statement);
132             samlResponse = buildResponse(profileResponse);
133         } catch (EncryptionException e) {
134             log.error("Error encrypting SAML response", e);
135             throw new ProfileException("Error encrypting SAML response", e);
136         }
137         if (log.isDebugEnabled()) {
138             log.debug("built saml2 response: " + samlResponse);
139         }
140
141         // encode response
142         try {
143             HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
144             encoder.setMetadataProvider(getMetadataProvider());
145             encoder.setRelyingParty(getRelyingPartyConfiguration(providerId).getRelyingPartyId());
146             encoder.setResponse((HttpServletResponse) response.getRawResponse());
147             encoder.setSAMLMessage(samlResponse);
148             encoder.encode();
149         } catch (BindingException e) {
150             log.error("Error encoding attribute query response", e);
151             throw new ProfileException("Error encoding attribute query response", e);
152         }
153     }
154 }