2 * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package edu.internet2.middleware.shibboleth.idp.profile.saml1;
19 import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
20 import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
22 import javax.servlet.ServletException;
24 import org.apache.log4j.Logger;
25 import org.joda.time.DateTime;
26 import org.opensaml.common.SAMLObjectBuilder;
27 import org.opensaml.common.binding.BindingException;
28 import org.opensaml.saml1.core.Advice;
29 import org.opensaml.saml1.core.Assertion;
30 import org.opensaml.saml1.core.AttributeStatement;
31 import org.opensaml.saml1.core.Conditions;
32 import org.opensaml.saml1.core.Response;
33 import org.opensaml.saml1.core.Status;
34 import org.opensaml.saml1.core.StatusCode;
35 import org.opensaml.saml1.core.Subject;
36 import org.opensaml.saml1.core.SubjectStatement;
37 import org.opensaml.xml.encryption.EncryptionException;
39 import edu.internet2.middleware.shibboleth.common.attribute.filtering.AttributeFilteringException;
40 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolutionException;
43 * SAML 1 Attribute Query profile handler.
45 public class AttributeQuery extends AbstractSAML1ProfileHandler {
48 private static Logger log = Logger.getLogger(AttributeQuery.class);
51 public boolean processRequest(ProfileRequest request, ProfileResponse response) throws ServletException {
52 if (log.isDebugEnabled()) {
53 log.debug("begin processRequest");
56 // get message from the decoder
57 org.opensaml.saml1.core.AttributeQuery message = null;
59 message = (org.opensaml.saml1.core.AttributeQuery) decodeMessage(request);
60 } catch (BindingException e) {
61 log.error("Error decoding attribute query message", e);
62 throw new ServletException("Error decoding attribute query message");
65 // get attribute statement from attribute authority
66 AttributeAuthority aa = new AttributeAuthority();
67 aa.setAttributeResolver(getAttributeResolver());
68 aa.setFilteringEngine(getFilteringEngine());
69 aa.setRelyingPartyConfiguration(getRelyingPartyConfiguration());
70 aa.setSecurityPolicy(getDecoder().getSecurityPolicy());
71 aa.setRequest(request);
72 AttributeStatement statement = null;
74 statement = aa.performAttributeQuery(message);
75 } catch (AttributeResolutionException e) {
76 log.error("Error resolving attributes", e);
77 throw new ServletException("Error resolving attributes");
78 } catch (FilteringException e) {
79 log.error("Error filtering attributes", e);
80 throw new ServletException("Error filtering attributes");
84 Response samlResponse = null;
86 samlResponse = buildResponse(message, request.getRemoteHost(), new DateTime(), statement);
87 } catch (EncryptionException e) {
88 log.error("Error encrypting SAML response", e);
89 throw new ServletException("Error encrypting SAML response");
91 if (log.isDebugEnabled()) {
92 log.debug("built saml1 response: " + samlResponse);
97 encodeResponse(samlResponse);
98 } catch (BindingException e) {
99 log.error("Error encoding attribute query response", e);
100 throw new ServletException("Error encoding attribute query response");
107 * This builds the response for this SAML request.
109 * @param message <code>AttributeQuery</code>
110 * @param dest <code>String</code>
111 * @param issueInstant <code>DateTime</code>
112 * @param statement <code>AttributeStatement</code>
113 * @return <code>Response</code>
114 * @throws EncryptionException if an error occurs attempting to encrypt data
116 private Response buildResponse(org.opensaml.saml1.core.AttributeQuery message, String dest, DateTime issueInstant,
117 AttributeStatement statement) throws EncryptionException {
118 SAMLObjectBuilder<Response> responseBuilder = (SAMLObjectBuilder<Response>) getBuilderFactory().getBuilder(
119 Response.DEFAULT_ELEMENT_NAME);
121 * required: samlp:Status, ID, Version, IssueInstant
123 Response response = responseBuilder.buildObject();
124 response.setVersion(SAML_VERSION);
125 response.setID(getIdGenerator().generateIdentifier());
126 response.setInResponseTo(getDecoder().getSecurityPolicy().getIssuer().toString());
127 response.setIssueInstant(issueInstant);
128 response.setRecipient(dest);
130 response.setStatus(buildStatus());
131 response.getAssertions().add(buildAssertion(message.getSubject(), issueInstant, statement));
136 * This builds the status response for this SAML request.
138 * @return <code>Status</code>
140 private Status buildStatus() {
142 SAMLObjectBuilder<Status> statusBuilder = (SAMLObjectBuilder<Status>) getBuilderFactory().getBuilder(
143 Status.DEFAULT_ELEMENT_NAME);
144 Status status = statusBuilder.buildObject();
147 SAMLObjectBuilder<StatusCode> statusCodeBuilder = (SAMLObjectBuilder<StatusCode>) getBuilderFactory()
148 .getBuilder(StatusCode.DEFAULT_ELEMENT_NAME);
149 StatusCode statusCode = statusCodeBuilder.buildObject();
150 statusCode.setValue("Success");
151 status.setStatusCode(statusCode);
156 * This builds the assertion for this SAML request.
158 * @param messageSubject <code>Subject</code>
159 * @param issueInstant <code>DateTime</code>
160 * @param statement <code>AttributeStatement</code> of attributes
161 * @return <code>Assertion</code>
162 * @throws EncryptionException if an error occurs attempting to encrypt data
164 private Assertion buildAssertion(Subject messageSubject, DateTime issueInstant, AttributeStatement statement)
165 throws EncryptionException {
167 SAMLObjectBuilder<Assertion> assertionBuilder = (SAMLObjectBuilder<Assertion>) getBuilderFactory().getBuilder(
168 Assertion.DEFAULT_ELEMENT_NAME);
170 * required: saml:Issuer, ID, Version, IssueInstant
172 Assertion assertion = assertionBuilder.buildObject();
173 assertion.setID(getIdGenerator().generateIdentifier());
174 assertion.setIssueInstant(issueInstant);
175 assertion.setVersion(SAML_VERSION);
176 assertion.setIssuer(getRelyingPartyConfiguration().getProviderID());
179 assertion.getSubjectStatements().add(buildSubjectStatement(messageSubject));
181 assertion.setConditions(buildConditions(issueInstant));
183 assertion.setAdvice(buildAdvice());
184 // add attribute statement
185 assertion.getAttributeStatements().add(statement);
190 * This builds the subject statement for this SAML request.
192 * @param messageSubject <code>Subject</code>
193 * @return <code>SubjectStatement</code>
195 private SubjectStatement buildSubjectStatement(Subject messageSubject) {
197 SAMLObjectBuilder<SubjectStatement> subjectStatementBuilder = (SAMLObjectBuilder<SubjectStatement>) getBuilderFactory()
198 .getBuilder(SubjectStatement.DEFAULT_ELEMENT_NAME);
199 SubjectStatement subjectStatement = subjectStatementBuilder.buildObject();
200 subjectStatement.setSubject(messageSubject);
201 return subjectStatement;
205 * This builds the conditions for this SAML request.
207 * @param issueInstant <code>DateTime</code>
208 * @return <code>Conditions</code>
210 private Conditions buildConditions(DateTime issueInstant) {
211 SAMLObjectBuilder<Conditions> conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory()
212 .getBuilder(Conditions.DEFAULT_ELEMENT_NAME);
213 Conditions conditions = conditionsBuilder.buildObject();
214 conditions.setNotBefore(issueInstant);
215 // TODO conditions.setNotOnOrAfter();
216 // TODO add additional conditions : conditions.getConditions().add(Condition);
217 // TODO what about AudienceRestriction, OneTimeUse, ProxyRestriction?
222 * This builds the advice for this SAML request.
224 * @return <code>Advice</code>
226 private Advice buildAdvice() {
227 SAMLObjectBuilder<Advice> adviceBuilder = (SAMLObjectBuilder<Advice>) getBuilderFactory().getBuilder(
228 Advice.DEFAULT_ELEMENT_NAME);
229 Advice advice = adviceBuilder.buildObject();
230 // advice.getAssertionIDReferences().add();
231 // advice.getAssertionURIReferences().add();
232 // advice.getAssertions().add();
233 // advice.getEncryptedAssertions().add();
234 // advice.addNamespace(namespace);