78c4c3e2a8212bb8d518f698d25889f70c2e512e
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / saml2 / AbstractAttributeQuery.java
1 /*
2  * Copyright [2006] [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
22 import org.apache.log4j.Logger;
23 import org.joda.time.DateTime;
24 import org.opensaml.common.binding.BindingException;
25 import org.opensaml.common.binding.MessageDecoder;
26 import org.opensaml.common.binding.MessageEncoder;
27 import org.opensaml.saml2.core.Assertion;
28 import org.opensaml.saml2.core.AttributeQuery;
29 import org.opensaml.saml2.core.AttributeStatement;
30 import org.opensaml.saml2.core.Response;
31 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
32
33 import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
34 import edu.internet2.middleware.shibboleth.common.attribute.SAML2AttributeAuthority;
35 import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethAttributeRequestContext;
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.common.relyingparty.RelyingPartyConfiguration;
40 import edu.internet2.middleware.shibboleth.common.relyingparty.saml2.AttributeQueryConfiguration;
41 import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
42 import edu.internet2.middleware.shibboleth.idp.session.Session;
43
44 /**
45  * SAML 2.0 Attribute Query profile handler.
46  */
47 public abstract class AbstractAttributeQuery extends AbstractSAML2ProfileHandler {
48
49     /** Class logger. */
50     private static Logger log = Logger.getLogger(AbstractAttributeQuery.class);
51
52     /**
53      * Gets the {@link AttributeQueryConfiguration} for the service provider identified by the given ID.
54      * 
55      * @param spId entity ID of the service provider
56      * 
57      * @return configuration for the given service provider or null
58      */
59     protected AttributeQueryConfiguration getAttributeQueryConfiguration(String spId) {
60         return (AttributeQueryConfiguration) getProfileConfiguration(spId, AttributeQueryConfiguration.PROFILE_ID);
61     }
62
63     /**
64      * Gets the attribute authority for the service provider identified by the given ID.
65      * 
66      * @param spId entity ID of the service provider
67      * 
68      * @return attribute authority for the service provider or null
69      */
70     protected SAML2AttributeAuthority getAttributeAuthority(String spId) {
71         AttributeQueryConfiguration config = getAttributeQueryConfiguration(spId);
72         if (config != null) {
73             return config.getAttributeAuthority();
74         }
75
76         return null;
77     }
78
79     /** {@inheritDoc} */
80     public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
81             throws ProfileException {
82         MessageDecoder<ServletRequest> decoder = getMessageDecoder(request);
83         populateMessageDecoder(decoder);
84         decoder.setRequest(request.getRawRequest());
85
86         // get message from the decoder
87         AttributeQuery attributeQuery = null;
88         try {
89             decoder.decode();
90             if (log.isDebugEnabled()) {
91                 log.debug("decoded http servlet request");
92             }
93             attributeQuery = (AttributeQuery) decoder.getSAMLMessage();
94         } catch (BindingException e) {
95             log.error("Error decoding attribute query message", e);
96             throw new ProfileException("Error decoding attribute query message");
97         }
98
99         String spEntityId = attributeQuery.getIssuer().getValue();
100         String userSessionId = getUserSessionId(request);
101         Session userSession = getSessionManager().getSession(userSessionId);
102         RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(spEntityId);
103         AttributeQueryConfiguration profileConfig = getAttributeQueryConfiguration(spEntityId);
104         DateTime issueInstant = new DateTime();
105
106         ShibbolethAttributeRequestContext attributeRequestContext = buildAttributeRequestContext(spEntityId,
107                 userSession, request);
108
109         // resolve attributes with the attribute authority
110         AttributeStatement attributeStatement = null;
111         try {
112             SAML2AttributeAuthority attributeAuthority = profileConfig.getAttributeAuthority();
113             attributeStatement = attributeAuthority.performAttributeQuery(attributeRequestContext);
114         } catch (AttributeRequestException e) {
115             log.error("Error resolving attributes", e);
116             throw new ProfileException("Error resolving attributes", e);
117         }
118
119         // construct attribute response
120         Response samlResponse = getResponseBuilder().buildObject();
121         populateStatusResponse(samlResponse, issueInstant, attributeQuery, rpConfig);
122
123         Assertion assertion = buildAssertion(issueInstant, rpConfig, profileConfig);
124         assertion.getAttributeStatements().add(attributeStatement);
125         samlResponse.getAssertions().add(assertion);
126
127         signAssertion(assertion, rpConfig, profileConfig);
128         signResponse(samlResponse, rpConfig, profileConfig);
129
130         MessageEncoder<ServletResponse> messageEncoder = getMessageEncoder(response);
131         populateMessageEncoder(messageEncoder);
132         messageEncoder.setRelyingParty(spEntityId);
133         messageEncoder.setSAMLMessage(samlResponse);
134
135         try {
136             messageEncoder.encode();
137         } catch (BindingException e) {
138             // TODO
139         }
140     }
141
142     /**
143      * Builds an attribute request context for this request.
144      * 
145      * @param spEntityId entity ID of the service provider
146      * @param userSession current user's session
147      * @param request current request
148      * 
149      * @return the attribute request context
150      * 
151      * @throws ProfileException thrown if the metadata information can not be located for the given service provider
152      */
153     protected ShibbolethAttributeRequestContext buildAttributeRequestContext(String spEntityId, Session userSession,
154             ProfileRequest<ServletRequest> request) throws ProfileException {
155         ServiceInformation spInformation = userSession.getServiceInformation(spEntityId);
156         ShibbolethAttributeRequestContext requestContext = null;
157         try {
158             requestContext = new ShibbolethAttributeRequestContext(getMetadataProvider(),
159                     getRelyingPartyConfiguration(spEntityId));
160             requestContext.setPrincipalName(userSession.getPrincipalID());
161             requestContext.setPrincipalAuthenticationMethod(spInformation.getAuthenticationMethod()
162                     .getAuthenticationMethod());
163             requestContext.setRequest(request.getRawRequest());
164             return requestContext;
165         } catch (MetadataProviderException e) {
166             log.error("Error creating ShibbolethAttributeRequestContext", e);
167             throw new ProfileException("Error retrieving metadata", e);
168         }
169     }
170 }