import org.opensaml.saml2.core.AttributeQuery;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.ws.security.SecurityPolicyException;
import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
import edu.internet2.middleware.shibboleth.common.attribute.SAML2AttributeAuthority;
AttributeQueryRequestContext requestContext = new AttributeQueryRequestContext(request, response);
getMessageDecoder(requestContext);
-
- decodeRequest(requestContext);
- buildResponse(requestContext);
+ try {
+ decodeRequest(requestContext);
+ buildResponse(requestContext);
+ } catch (SecurityPolicyException e) {
+ buildErrorResponse(requestContext, e);
+ }catch (AttributeRequestException e){
+ buildErrorResponse(requestContext, e);
+ }
getMessageEncoder(requestContext);
* @param requestContext request context contianing the request to decode
*
* @throws ProfileException throw if there is a problem decoding the request
+ * @throws SecurityPolicyException thrown if the message was decoded properly but did not meet the necessary
+ * security policy requirements
*/
- protected void decodeRequest(AttributeQueryRequestContext requestContext)
- throws ProfileException {
+ protected void decodeRequest(AttributeQueryRequestContext requestContext) throws ProfileException,
+ SecurityPolicyException {
try {
requestContext.getMessageDecoder().decode();
if (log.isDebugEnabled()) {
log.debug("decoded http servlet request");
}
- requestContext.setAttributeQuery((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
} catch (BindingException e) {
log.error("Error decoding attribute query message", e);
throw new ProfileException("Error decoding attribute query message");
+ } finally{
+ requestContext.setAttributeQuery((AttributeQuery) requestContext.getMessageDecoder().getSAMLMessage());
}
}
* @param requestContext current request context
*
* @throws ProfileException thrown if there is a problem creating the SAML response
+ * @throws AttributeRequestException thrown if there is a problem resolving attributes
*/
- protected void buildResponse(AttributeQueryRequestContext requestContext) throws ProfileException {
+ protected void buildResponse(AttributeQueryRequestContext requestContext) throws ProfileException,
+ AttributeRequestException {
DateTime issueInstant = new DateTime();
// create the attribute statement
Response samlResponse = getResponseBuilder().buildObject();
populateStatusResponse(samlResponse, issueInstant, requestContext.getAttributeQuery(), requestContext
.getRelyingPartyConfiguration());
-
+
// TODO handle subject
samlResponse.getAssertions().add(assertion);
signAssertion(assertion, requestContext.getRelyingPartyConfiguration(), requestContext
.getProfileConfiguration());
+ Status status = buildStatus(StatusCode.SUCCESS_URI, null, null);
+ samlResponse.setStatus(status);
+
requestContext.setAttributeQueryResponse(samlResponse);
}
* @return attribute statement resulting from the query
*
* @throws ProfileException thrown if there is a problem making the query
+ * @throws AttributeRequestException thrown if there is a problem resolving attributes
*/
protected AttributeStatement buildAttributeStatement(AttributeQueryRequestContext requestContext)
- throws ProfileException {
+ throws ProfileException, AttributeRequestException {
ShibbolethAttributeRequestContext attributeRequestContext = buildAttributeRequestContext(requestContext
.getRelyingPartyId(), requestContext.getUserSession(), requestContext.getProfileRequest());
return attributeAuthority.performAttributeQuery(attributeRequestContext);
} catch (AttributeRequestException e) {
log.error("Error resolving attributes", e);
- throw new ProfileException("Error resolving attributes", e);
+ throw e;
}
}
*/
protected ShibbolethAttributeRequestContext buildAttributeRequestContext(String spEntityId, Session userSession,
ProfileRequest<ServletRequest> request) throws ProfileException {
- ServiceInformation spInformation = userSession.getServiceInformation(spEntityId);
ShibbolethAttributeRequestContext requestContext = null;
try {
requestContext = new ShibbolethAttributeRequestContext(getMetadataProvider(),
getRelyingPartyConfiguration(spEntityId));
requestContext.setPrincipalName(userSession.getPrincipalID());
- requestContext.setPrincipalAuthenticationMethod(spInformation.getAuthenticationMethod()
- .getAuthenticationMethod());
+ if (userSession != null) {
+ ServiceInformation spInformation = userSession.getServiceInformation(spEntityId);
+ requestContext.setPrincipalAuthenticationMethod(spInformation.getAuthenticationMethod()
+ .getAuthenticationMethod());
+ }
requestContext.setRequest(request.getRawRequest());
return requestContext;
} catch (MetadataProviderException e) {
}
/**
+ * Constructs an SAML response message carrying a request error.
+ *
+ * @param requestContext current request context
+ * @param error the encountered error
+ */
+ protected void buildErrorResponse(AttributeQueryRequestContext requestContext, Exception error) {
+ DateTime issueInstant = new DateTime();
+ Response samlResponse = getResponseBuilder().buildObject();
+ populateStatusResponse(samlResponse, issueInstant, requestContext.getAttributeQuery(), requestContext
+ .getRelyingPartyConfiguration());
+
+ Status status = buildStatus(StatusCode.RESPONDER_URI, StatusCode.REQUEST_DENIED_URI, error
+ .getLocalizedMessage());
+ samlResponse.setStatus(status);
+
+ requestContext.setAttributeQueryResponse(samlResponse);
+ }
+
+ /**
* Writes an aduit log entry indicating the successful response to the attribute request.
*
* @param requestContext current request context
protected void writeAuditLogEntry(AttributeQueryRequestContext requestContext) {
AuditLogEntry auditLogEntry = new AuditLogEntry();
auditLogEntry.setMessageProfile(getProfileId());
- auditLogEntry.setPrincipalAuthenticationMethod(requestContext.getUserSession().getServiceInformation(
- requestContext.getRelyingPartyId()).getAuthenticationMethod().getAuthenticationMethod());
- auditLogEntry.setPrincipalId(requestContext.getUserSession().getPrincipalID());
+
+ if(requestContext.getUserSession() != null){
+ auditLogEntry.setPrincipalAuthenticationMethod(requestContext.getUserSession().getServiceInformation(
+ requestContext.getRelyingPartyId()).getAuthenticationMethod().getAuthenticationMethod());
+ auditLogEntry.setPrincipalId(requestContext.getUserSession().getPrincipalID());
+ }
+
auditLogEntry.setProviderId(requestContext.getRelyingPartyConfiguration().getProviderId());
auditLogEntry.setRelyingPartyId(requestContext.getRelyingPartyId());
auditLogEntry.setRequestBinding(requestContext.getMessageDecoder().getBindingURI());
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
- default-autowire="byType">
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- Spring configuration file that boostraps OpenSAML -->
<bean id="shibboleth.OpensamlConfig" class="edu.internet2.middleware.shibboleth.common.config.OpensamlConfigBean" lazy-init="false">
<property name="namespaceAware" value="true" />
</bean>
- <bean id="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactory" class="org.opensaml.common.binding.security.SAMLSecurityPolicyFactory">
+ <bean id="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactoryNoIssuerAuth"
+ class="org.opensaml.common.binding.security.SAMLSecurityPolicyFactory">
<property name="issuerRole">
<bean id="shibboleth.SAML2AttributeQueryRole" class="javax.xml.namespace.QName">
<constructor-arg value="urn:oasis:names:tc:SAML:2.0:metadata" />
<ref bean="shibboleth.MessageIssueInstantRuleFactory" />
</list>
</property>
+ <property name="requiredAuthenticatedIssuer" value="false" />
+ </bean>
+
+ <bean id="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactoryIssuerAuth"
+ class="org.opensaml.common.binding.security.SAMLSecurityPolicyFactory"
+ parent="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactoryNoIssuerAuth">
+ <property name="requiredAuthenticatedIssuer" value="true" />
</bean>
<bean id="shibboleth.SAML2ProtocolMessageRuleFactory" class="org.opensaml.saml2.binding.security.SAML2ProtocolMessageRuleFactory" />
<key>
<value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST</value>
</key>
- <bean id="shibboleth.SAML2HttpPostDecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPPostDecoderBuilder" />
+ <bean id="shibboleth.SAML2HttpPostDecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPPostDecoderBuilder">
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
</entry>
<entry>
<key>
<value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</value>
</key>
- <bean id="shibboleth.SAML2HttpRedirectDecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoderBuilder" />
+ <bean id="shibboleth.SAML2HttpRedirectDecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoderBuilder" >
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
</entry>
<entry>
<key>
<value>urn:oasis:names:tc:SAML:2.0:bindings:SOAP</value>
</key>
- <bean id="shibboleth.SAML2HttpSoap11DecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPSOAP11DecoderBuilder" />
+ <bean id="shibboleth.SAML2HttpSoap11DecoderBuilder" class="org.opensaml.saml2.binding.decoding.HTTPSOAP11DecoderBuilder" >
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
</entry>
<entry>
<key>
<value>urn:oasis:names:tc:SAML:1.0:profiles:browser-post</value>
</key>
- <bean id="shibboleth.SAML1HttpPostDecoderBuilder" class="org.opensaml.saml1.binding.decoding.HTTPPostDecoderBuilder" />
+ <bean id="shibboleth.SAML1HttpPostDecoderBuilder" class="org.opensaml.saml1.binding.decoding.HTTPPostDecoderBuilder" >
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
</entry>
<entry>
<key>
<value>urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding</value>
</key>
- <bean id="shibboleth.SAML1HttpSoap11DecoderBuilder" class="org.opensaml.saml1.binding.decoding.HTTPSOAP11DecoderBuilder" />
+ <bean id="shibboleth.SAML1HttpSoap11DecoderBuilder" class="org.opensaml.saml1.binding.decoding.HTTPSOAP11DecoderBuilder" >
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
</entry>
</map>
</property>
<?xml version="1.0" encoding="UTF-8"?>
<ProfileHandlerGroup xmlns="urn:mace:shibboleth:2.0:profile-handler"
- xmlns:idpProfile="urn:mace:shibboleth:2.0:idp:profiles"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:profile-handler classpath:/schema/shibboleth-2.0-profile-handler.xsd
+ xmlns:idpProfile="urn:mace:shibboleth:2.0:idp:profiles" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:profile-handler classpath:/schema/shibboleth-2.0-profile-handler.xsd
urn:mace:shibboleth:2.0:idp:profiles classpath:/schema/shibboleth-2.0-idp-profile.xsd">
<ErrorHandler xsi:type="JSPErrorHandler" jspPagePath="/error.jsp" />
<ProfileHandler xsi:type="idpProfile:Status">
<RequestPath>/shibboleth/IdP/status</RequestPath>
</ProfileHandler>
-
+
<ProfileHandler xsi:type="idpProfile:SAML2AttributeQuery"
- securityPolicyFactoryId="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactory">
- <RequestPath>/IdP/saml2/SOAP/AttributeQuery</RequestPath>
+ securityPolicyFactoryId="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactoryNoIssuerAuth">
+ <RequestPath>/IdP/saml2/SOAP/AttributeQueryNoAuth</RequestPath>
</ProfileHandler>
-<!--
- <ProfileHandler xsi:type="idpProfile:SAML2SSO">
- <RequestPath>/IdP/saml2/HTTP/SSO</RequestPath>
+ <ProfileHandler xsi:type="idpProfile:SAML2AttributeQuery"
+ securityPolicyFactoryId="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactoryIssuerAuth">
+ <RequestPath>/IdP/saml2/SOAP/AttributeQuery</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="idpProfile:SAML2AttributeQuery">
+ <!--
+ <ProfileHandler xsi:type="idpProfile:SAML2SSO">
+ <RequestPath>/IdP/saml2/HTTP/SSO</RequestPath>
+ </ProfileHandler>
+
+ <ProfileHandler xsi:type="idpProfile:SAML2AttributeQuery">
<RequestPath>/IdP/saml2/SOAP/attribute</RequestPath>
- </ProfileHandler>
--->
+ </ProfileHandler>
+ -->
</ProfileHandlerGroup>
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.system.conf1;
+import java.io.StringWriter;
+
import org.joda.time.DateTime;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.SAMLVersion;
*/
public class SAML2AttributeQueryTestCase extends BaseConf1TestCase {
- public void testAttributeQuery() throws Exception {
+ /** Tests a request where the Issuer can not be authenticated. */
+ public void testUnathenticatedIssuerAttributeQuery() throws Exception {
AttributeQuery query = buildAttributeQuery();
String soapMessage = getSOAPMessage(query);
ShibbolethProfileHandlerManager handlerManager = (ShibbolethProfileHandlerManager) getApplicationContext()
.getBean("shibboleth.ProfileHandler");
ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
-
- return;
+ assertNotNull(handler);
-// ProfileRequest profileRequest = new ShibbolethProfileRequest(servletRequest);
-// ProfileResponse profileResponse = new ShibbolethProfileResponse(servletResponse);
-// handler.processRequest(profileRequest, profileResponse);
+ // Process request
+ ProfileRequest profileRequest = new ShibbolethProfileRequest(servletRequest);
+ ProfileResponse profileResponse = new ShibbolethProfileResponse(servletResponse);
+ handler.processRequest(profileRequest, profileResponse);
+ String response = servletResponse.getContentAsString();
+ assertTrue(response.contains("urn:oasis:names:tc:SAML:2.0:status:Responder"));
+ assertTrue(response.contains("urn:oasis:names:tc:SAML:2.0:status:RequestDenied"));
}
/**
Marshaller marshaller = marshallerFactory.getMarshaller(envelope);
Element envelopeElem = marshaller.marshall(envelope);
- return XMLHelper.nodeToString(envelopeElem);
+ StringWriter writer = new StringWriter();
+ XMLHelper.writeNode(envelopeElem, writer);
+ return writer.toString();
}
}
\ No newline at end of file