</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
- <xsd:attribute name="decodingBinding" type="xsd:anyURI"
- default="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
- <xsd:annotation>
- <xsd:documentation>
- The URI of the binding used when decoding requests from relying parties.
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="securityPolicyFactoryId" type="xsd:string"
- default="shibboleth.SAML2SSOMessageSecurityPolicyFactory">
- <xsd:annotation>
- <xsd:documentation>
- The component ID of the security policy factory to use with the profile handler.
-
- This setting should not be changed from its default unless the deployer fully understands
- the inter-relationship between IdP components.
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="outboundBindingEnumeration"
- default="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
- <xsd:annotation>
- <xsd:documentation>
- An ordered list of outbound bindings supported by this profile handler. The order provided
- establishs the precedence given the bindings such that, from the left to right, the first
- binding also supported by the relying party will be used.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:list itemType="xsd:anyURI" />
- </xsd:simpleType>
- </xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:documentation>Configuration type for SAML 2 Attribute Query profile handlers.</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
- <xsd:extension base="SAML2ProfileHandler">
- <xsd:attribute name="securityPolicyFactoryId" type="xsd:string"
- default="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactory">
- <xsd:annotation>
- <xsd:documentation>
- The component ID of the security policy factory to use with the profile handler.
-
- This setting should not be changed from its default unless the deployer fully understands
- the inter-relationship between IdP components.
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
+ <xsd:extension base="SAML2ProfileHandler" />
</xsd:complexContent>
</xsd:complexType>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
- <xsd:attribute name="outboundBindingEnumeration"
- default="urn:oasis:names:tc:SAML:1.0:profiles:browser-post">
- <xsd:annotation>
- <xsd:documentation>
- An ordered list of outbound bindings supported by this profile handler. The order provided
- establishs the precedence given the bindings such that, from the left to right, the first
- binding also supported by the relying party will be used.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:list itemType="xsd:anyURI" />
- </xsd:simpleType>
- </xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:documentation>Configuration type for SAML 1 Attribute Query profile handlers.</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
- <xsd:extension base="SAML1ProfileHandler">
- <xsd:attribute name="securityPolicyFactoryId" type="xsd:string"
- default="shibboleth.SAML1AttributeQueryMessageSecurityPolicyFactory">
- <xsd:annotation>
- <xsd:documentation>
- The component ID of the security policy factory to use with the profile handler.
-
- This setting should not be changed from its default unless the deployer fully understands
- the inter-relationship between IdP components.
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
+ <xsd:extension base="SAML1ProfileHandler" />
</xsd:complexContent>
</xsd:complexType>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="IdPProfileHandlerType">
- <xsd:attribute name="messageDecoderFactoryId" type="xsd:string"
- default="shibboleth.MessageDecoderFactory">
+ <xsd:attribute name="idGeneratorId" type="xsd:string" default="shibboleth.IdGenerator">
<xsd:annotation>
<xsd:documentation>
- The component ID of the message decoder to use with the profile handler.
+ The component ID of a generator used to generated things like response and assertion IDs.
This setting should not be changed from its default unless the deployer fully understands
the inter-relationship between IdP components.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
- <xsd:attribute name="messageEncoderFactoryId" type="xsd:string"
- default="shibboleth.MessageEncoderFactory">
+ <xsd:attribute name="inboundBinding" type="xsd:anyURI" use="required">
<xsd:annotation>
<xsd:documentation>
- The component ID of the message encoder to use with the profile handler.
-
- This setting should not be changed from its default unless the deployer fully understands
- the inter-relationship between IdP components.
+ The SAML message binding used by inbound messages.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
- <xsd:attribute name="idGeneratorId" type="xsd:string" default="shibboleth.IdGenerator">
+ <xsd:attribute name="outboundBindingEnumeration" >
<xsd:annotation>
<xsd:documentation>
- The component ID of a generator used to generated things like response and assertion IDs.
-
- This setting should not be changed from its default unless the deployer fully understands
- the inter-relationship between IdP components.
+ An ordered list of outbound bindings supported by this profile handler. The order provided
+ establishes the precedence given the bindings such that, from the left to right, the first
+ binding also supported by the relying party will be used.
</xsd:documentation>
</xsd:annotation>
+ <xsd:simpleType>
+ <xsd:list itemType="xsd:anyURI" />
+ </xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
<RequestPath>/status</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="ShibbolethSSO">
+ <ProfileHandler xsi:type="ShibbolethSSO"
+ inboundBinding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
+ outboundBindingEnumeration="urn:oasis:names:tc:SAML:1.0:profiles:browser-post
+ urn:oasis:names:tc:SAML:1.0:profiles:artifact-01">
<RequestPath>/shibboleth/SSO</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="SAML1AttributeQuery">
+ <ProfileHandler xsi:type="SAML1AttributeQuery"
+ inboundBinding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
+ outboundBinding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding">
<RequestPath>/saml1/SOAP/AttributeQuery</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="SAML2SSO">
+ <ProfileHandler xsi:type="SAML2SSO"
+ inboundBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ outboundBindingEnumeration="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
+ urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact">
<RequestPath>/saml2/POST/SSO</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="SAML2SSO" decodingBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect">
+ <ProfileHandler xsi:type="SAML2SSO"
+ inboundBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ outboundBindingEnumeration="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
+ urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact">
<RequestPath>/saml2/Redirect/SSO</RequestPath>
</ProfileHandler>
- <ProfileHandler xsi:type="SAML2AttributeQuery">
+ <ProfileHandler xsi:type="SAML2AttributeQuery"
+ inboundBinding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+ outboundBindingEnumeration="urn:oasis:names:tc:SAML:2.0:bindings:SOAP">
<RequestPath>/saml2/SOAP/AttributeQuery</RequestPath>
</ProfileHandler>
</AuthenticationHandler>
<AuthenticationHandler xsi:type="UsernamePassword"
- jaasConfigurationLocation="file://$IDP_HOME/conf/login.confg">
+ jaasConfigurationLocation="file://$IDP_HOME/conf/login.config">
<AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthenticationMethod>
</AuthenticationHandler>
<?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">
-
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
+
<!-- Spring configuration file that boostraps OpenSAML -->
- <bean id="shibboleth.OpensamlConfig" class="edu.internet2.middleware.shibboleth.common.config.OpensamlConfigBean" lazy-init="false">
+ <bean id="shibboleth.OpensamlConfig" class="edu.internet2.middleware.shibboleth.common.config.OpensamlConfigBean"
+ lazy-init="false">
<constructor-arg>
<list>
<bean id="default" class="org.opensaml.util.resource.ClasspathResource">
</bean>
<bean id="saml2MetadataQuery" class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/saml2-metadata-query-config.xml" />
- </bean>
+ </bean>
</list>
</constructor-arg>
</bean>
-
+
<bean id="shibboleth.IdGenerator" class="org.opensaml.common.impl.SecureRandomIdentifierGenerator">
<constructor-arg value="SHA1PRNG" />
</bean>
- <bean id="shibboleth.VelocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean" >
+ <bean id="shibboleth.VelocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
<prop key="resource.loader">classpath, string</prop>
</props>
</property>
</bean>
-
- <bean id="shibboleth.TemplateEngine" class="edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.dataConnector.TemplateEngine" >
+
+ <bean id="shibboleth.TemplateEngine"
+ class="edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.dataConnector.TemplateEngine">
<constructor-arg ref="shibboleth.VelocityEngine" />
</bean>
<property name="ignoreElementContentWhitespace" value="true" />
<property name="namespaceAware" value="true" />
</bean>
-
- <bean id="shibboleth.SAML2SSOMessageSecurityPolicyFactory"
- parent="shibboleth.BaseSAML2SecurityPolicyFactory">
- <property name="issuerRole">
- <bean id="shibboleth.SAML2SSORole" class="javax.xml.namespace.QName">
- <constructor-arg value="urn:oasis:names:tc:SAML:2.0:metadata" />
- <constructor-arg value="SPSSODescriptor" />
+
+ <util:map id="shibboleth.MessageDecoders">
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpPostDecoder" class="org.opensaml.saml2.binding.decoding.HTTPPostDecoder">
+ <constructor-arg ref="shibboleth.ParserPool" />
</bean>
- </property>
- </bean>
-
- <bean id="shibboleth.SAML2AttributeQueryMessageSecurityPolicyFactory"
- parent="shibboleth.BaseSAML2SecurityPolicyFactory">
- <property name="issuerRole">
- <bean id="shibboleth.SAML2AttributeQueryRole" class="javax.xml.namespace.QName">
- <constructor-arg value="urn:oasis:names:tc:SAML:2.0:metadata" />
- <constructor-arg value="SPSSODescriptor" />
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpRedirectDecoder"
+ class="org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder">
+ <constructor-arg ref="shibboleth.ParserPool" />
</bean>
- </property>
- </bean>
-
- <bean id="shibboleth.BaseSAML2SecurityPolicyFactory" abstract="true" class="org.opensaml.common.binding.security.SAMLSecurityPolicyFactory">
- <property name="issuerProtocol" value="urn:oasis:names:tc:SAML:2.0:protocol" />
- <property name="policyRuleFactories">
- <list>
- <ref bean="shibboleth.SAML2ProtocolMessageRuleFactory" />
- <!-- Removed for testing -->
- <!-- ref bean="shibboleth.MessageIssueInstantRuleFactory" /-->
- </list>
- </property>
- <!-- Turn off for testing -->
- <property name="requiredAuthenticatedIssuer" value="false" />
- </bean>
-
- <bean id="shibboleth.SAML1AttributeQueryMessageSecurityPolicyFactory"
- parent="shibboleth.BaseSAML1SecurityPolicyFactory">
- <property name="issuerRole">
- <bean id="shibboleth.SAML1AttributeQueryRole" class="javax.xml.namespace.QName">
- <constructor-arg value="urn:oasis:names:tc:SAML:2.0:metadata" />
- <constructor-arg value="SPSSODescriptor" />
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact</value>
+ </key>
+ <bean id="shibboleth.SAML2HTTPArtifactDecoder"
+ class="org.opensaml.saml2.binding.decoding.HTTPArtifactDecoder">
+ <constructor-arg ref="shibboleth.ParserPool" />
</bean>
- </property>
- </bean>
-
- <bean id="shibboleth.BaseSAML1SecurityPolicyFactory" abstract="true" class="org.opensaml.common.binding.security.SAMLSecurityPolicyFactory">
- <property name="issuerProtocol" value="urn:oasis:names:tc:SAML:1.0:protocol" />
- <property name="policyRuleFactories">
- <list>
- <ref bean="shibboleth.SAML1ProtocolMessageRuleFactory" />
- <!-- Removed for testing -->
- <!-- ref bean="shibboleth.MessageIssueInstantRuleFactory" /-->
- </list>
- </property>
- <!-- Turn off for testing -->
- <property name="requiredAuthenticatedIssuer" value="false" />
- </bean>
-
- <bean id="shibboleth.SAML2ProtocolMessageRuleFactory" class="org.opensaml.saml2.binding.security.SAML2ProtocolMessageRuleFactory" />
-
- <bean id="shibboleth.SAML1ProtocolMessageRuleFactory" class="edu.internet2.middleware.shibboleth.common.binding.security.ShibbolethSAML1ProtocolMessageRuleFactory" />
-
- <bean id="shibboleth.MessageIssueInstantRuleFactory" class="org.opensaml.common.binding.security.IssueInstantRuleFactory">
- <property name="clockSkew" value="5" />
- <property name="expires" value="10" />
- </bean>
-
- <bean id="shibboleth.MessageEncoderFactory" class="org.opensaml.common.binding.encoding.MessageEncoderFactory">
- <property name="encoderBuilders">
- <map>
- <entry>
- <key>
- <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST</value>
- </key>
- <bean id="shibboleth.SAML2HttpPostEncoderBuilder" class="org.opensaml.saml2.binding.encoding.HTTPPostEncoderBuilder">
- <constructor-arg ref="shibboleth.VelocityEngine" />
- <constructor-arg value="/templates/saml2-post-binding.vm"/>
- </bean>
- </entry>
- <entry>
- <key>
- <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</value>
- </key>
- <bean id="shibboleth.SAML2HttpRedirectEncoderBuilder" class="org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoderBuilder" />
- </entry>
- <entry>
- <key>
- <value>urn:oasis:names:tc:SAML:2.0:bindings:SOAP</value>
- </key>
- <bean id="shibboleth.SAML2HttpSoap11EncoderBuilder" class="org.opensaml.saml2.binding.encoding.HTTPSOAP11EncoderBuilder" />
- </entry>
- <entry>
- <key>
- <value>urn:oasis:names:tc:SAML:1.0:profiles:browser-post</value>
- </key>
- <bean id="shibboleth.SAML1HttpPostEncoderBuilder" class="org.opensaml.saml1.binding.encoding.HTTPPostEncoderBuilder">
- <constructor-arg ref="shibboleth.VelocityEngine" />
- <constructor-arg value="/templates/saml1-post-binding.vm"/>
- </bean>
- </entry>
- <entry>
- <key>
- <value>urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding</value>
- </key>
- <bean id="shibboleth.SAML1HttpSoap11EncoderBuilder" class="org.opensaml.saml1.binding.encoding.HTTPSOAP11EncoderBuilder" />
- </entry>
- </map>
- </property>
- </bean>
-
- <bean id="shibboleth.MessageDecoderFactory" class="org.opensaml.common.binding.decoding.MessageDecoderFactory">
- <property name="decoderBuilders">
- <map>
- <entry>
- <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">
- <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" >
- <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" >
- <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" >
- <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" >
- <property name="parser" ref="shibboleth.ParserPool" />
- </bean>
- </entry>
- </map>
- </property>
- </bean>
-
- <bean id="shibboleth.SessionManager" class="edu.internet2.middleware.shibboleth.idp.session.impl.SessionManagerImpl" />
-
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:SOAP</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpSoap11Decoder"
+ class="org.opensaml.saml2.binding.decoding.HTTPSOAP11Decoder">
+ <constructor-arg ref="shibboleth.ParserPool" />
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:profiles:browser-post</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpPostDecoder" class="org.opensaml.saml1.binding.decoding.HTTPPostDecoder">
+ <constructor-arg ref="shibboleth.ParserPool" />
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:profiles:artifact-01</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpArtifactDecoder" class="org.opensaml.saml1.binding.encoding.HTTPArtifactDecoder">
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpSoap11Decoder"
+ class="org.opensaml.saml1.binding.decoding.HTTPSOAP11Decoder">
+ <property name="parser" ref="shibboleth.ParserPool" />
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:mace:shibboleth:1.0:profiles:AuthnRequest</value>
+ </key>
+ <bean id="shibboleth.ShibbolethSSODecoder"
+ class="org.opensaml.saml1.binding.decoding.ShibbolethSSODecoder">
+ </bean>
+ </entry>
+ </util:map>
+
+ <util:map id="shibboleth.MessageEncoders">
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpPostEncoder" class="org.opensaml.saml2.binding.encoding.HTTPPostEncoder">
+ <constructor-arg ref="shibboleth.VelocityEngine" />
+ <constructor-arg value="/templates/saml2-post-binding.vm" />
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpRedirectEncoder"
+ class="org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder" />
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact</value>
+ </key>
+ <bean id="shibboleth.SAML2HTTPArtifactEncoder"
+ class="org.opensaml.saml2.binding.decoding.HTTPArtifactEncoder">
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:2.0:bindings:SOAP</value>
+ </key>
+ <bean id="shibboleth.SAML2HttpSoap11Encoder" class="org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder" />
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:profiles:browser-post</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpPostEncoder" class="org.opensaml.saml1.binding.encoding.HTTPPostEncoder">
+ <constructor-arg ref="shibboleth.VelocityEngine" />
+ <constructor-arg value="/templates/saml1-post-binding.vm" />
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:profiles:artifact-01</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpArtifactEncoder" class="org.opensaml.saml1.binding.encoding.HTTPArtifactEncoder">
+ </bean>
+ </entry>
+ <entry>
+ <key>
+ <value>urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding</value>
+ </key>
+ <bean id="shibboleth.SAML1HttpSoap11EncoderBuilder"
+ class="org.opensaml.saml1.binding.encoding.HTTPSOAP11EncoderBuilder" />
+ </entry>
+ </util:map>
+
+ <bean id="shibboleth.SessionManager"
+ class="edu.internet2.middleware.shibboleth.idp.session.impl.SessionManagerImpl" />
+
<bean id="shibboleth.SAML1AttributeAuthority"
- class="edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAML1AttributeAuthority">
- <constructor-arg ref="shibboleth.AttributeResolver" />
- <property name="filteringEngine" ref="shibboleth.AttributeFilterEngine" />
+ class="edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAML1AttributeAuthority">
+ <constructor-arg ref="shibboleth.AttributeResolver" />
+ <property name="filteringEngine" ref="shibboleth.AttributeFilterEngine" />
</bean>
-
+
<bean id="shibboleth.SAML2AttributeAuthority"
- class="edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAML2AttributeAuthority">
- <constructor-arg ref="shibboleth.AttributeResolver" />
- <property name="filteringEngine" ref="shibboleth.AttributeFilterEngine" />
+ class="edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAML2AttributeAuthority">
+ <constructor-arg ref="shibboleth.AttributeResolver" />
+ <property name="filteringEngine" ref="shibboleth.AttributeFilterEngine" />
</bean>
-
+
<bean id="shibboleth.ServletAttributeExporter"
class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
</map>
</property>
</bean>
-
+
</beans>
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.config.profile;
import org.apache.log4j.Logger;
+import org.opensaml.xml.util.XMLHelper;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.w3c.dom.Element;
}
super.doParse(config, builder);
- builder.addPropertyReference("messageDecoderFactory", config.getAttributeNS(null,
- "messageDecoderFactoryId"));
+ builder.addPropertyReference("idGenerator", config.getAttributeNS(null, "idGeneratorId"));
- builder.addPropertyReference("messageEncoderFactory", config.getAttributeNS(null,
- "messageEncoderFactoryId"));
+ builder.addPropertyReference("messageDecoders", "shibboleth.MessageDecoders");
- builder.addPropertyReference("idGenerator", config.getAttributeNS(null, "idGeneratorId"));
+ builder.addPropertyReference("messageEncoders", "shibboleth.MessageEncoders");
+
+ builder.addPropertyValue("inboundBinding", config.getAttributeNodeNS(null, "inboundBinding"));
+
+ builder.addPropertyValue("supportedOutboundBindings", XMLHelper.getAttributeValueAsList(config
+ .getAttributeNodeNS(null, "outboundBindingEnumeration")));
}
}
\ No newline at end of file
/** {@inheritDoc} */
protected void doParse(Element config, BeanDefinitionBuilder builder) {
super.doParse(config, builder);
-
- builder.addPropertyReference("securityPolicyFactory", DatatypeHelper.safeTrimOrNullString(config
- .getAttributeNS(null, "securityPolicyFactoryId")));
}
}
\ No newline at end of file
/** {@inheritDoc} */
protected void doParse(Element config, BeanDefinitionBuilder builder) {
super.doParse(config, builder);
-
- builder.addPropertyReference("securityPolicyFactory", DatatypeHelper.safeTrimOrNullString(config
- .getAttributeNS(null, "securityPolicyFactoryId")));
}
}
\ No newline at end of file
"outboundBindingEnumeration")));
builder.addConstructorArg(DatatypeHelper.safeTrimOrNullString(config.getAttributeNS(null, "decodingBinding")));
-
- builder.addPropertyReference("securityPolicyFactory", DatatypeHelper.safeTrimOrNullString(config
- .getAttributeNS(null, "securityPolicyFactoryId")));
}
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.profile;
+import java.util.List;
+import java.util.Map;
+
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.opensaml.common.IdentifierGenerator;
import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.binding.encoding.SAMLMessageEncoder;
+import org.opensaml.log.Level;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.transport.InTransport;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractShibbolethProfileHandler;
+import edu.internet2.middleware.shibboleth.common.profile.provider.BaseSAMLProfileRequestContext;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
+import edu.internet2.middleware.shibboleth.idp.profile.saml2.BaseSAML2ProfileRequestContext;
import edu.internet2.middleware.shibboleth.idp.session.Session;
/**
/** SAML message audit log. */
private final Logger auditLog = Logger.getLogger(AuditLogEntry.AUDIT_LOGGER_NAME);
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(AbstractSAMLProfileHandler.class);
+
/** Generator of IDs which may be used for SAML assertions, requests, etc. */
private IdentifierGenerator idGenerator;
- /** Decoder used to extract message information from the inbound transport. */
- private SAMLMessageDecoder messageDecoder;
+ /** All the SAML message decoders configured for the IdP. */
+ private Map<String, SAMLMessageDecoder> messageDecoders;
+
+ /** All the SAML message encoders configured for the IdP. */
+ private Map<String, SAMLMessageEncoder> messageEncoders;
+
+ /** SAML message binding used by inbound messages. */
+ private String inboundBinding;
- /** Encoder used to bind information to the outbound message transport. */
- private SAMLMessageEncoder messageEncoder;
+ /** SAML message bindings that may be used by outbound messages. */
+ private List<String> supportedOutboundBindings;
/** Constructor. */
protected AbstractSAMLProfileHandler() {
}
/**
- * Gets the decoder used to extract message information from the inbound transport.
+ * Gets the SAML message binding used by inbound messages.
*
- * @return decoder used to extract message information from the inbound transport
+ * @return SAML message binding used by inbound messages
*/
- public SAMLMessageDecoder getMessageDecoder() {
- return messageDecoder;
+ public String getInboundBinding() {
+ return inboundBinding;
}
/**
- * Gets the encoder used to bind information to the outbound message transport.
+ * Gets all the SAML message decoders configured for the IdP indexed by SAML binding URI.
*
- * @return encoder used to bind information to the outbound message transport
+ * @return SAML message decoders configured for the IdP indexed by SAML binding URI
*/
- public SAMLMessageEncoder getMessageEncoder() {
- return messageEncoder;
+ public Map<String, SAMLMessageDecoder> getMessageDecoders() {
+ return messageDecoders;
+ }
+
+ /**
+ * Gets all the SAML message encoders configured for the IdP indexed by SAML binding URI.
+ *
+ * @return SAML message encoders configured for the IdP indexed by SAML binding URI
+ */
+ public Map<String, SAMLMessageEncoder> getMessageEncoders() {
+ return messageEncoders;
}
/**
}
/**
+ * Gets the SAML message bindings that may be used by outbound messages.
+ *
+ * @return SAML message bindings that may be used by outbound messages
+ */
+ public List<String> getSupportedOutboundBindings() {
+ return supportedOutboundBindings;
+ }
+
+ /**
+ * Gets the user's session, if there is one.
+ *
+ * @param inTransport current inbound transport
+ *
+ * @return user's session
+ */
+ protected Session getUserSession(InTransport inTransport) {
+ String sessionId = getUserSessionId(inTransport);
+ return getSessionManager().getSession(sessionId);
+ }
+
+ /**
* Gets the user's session ID from the current request.
*
* @param inTransport current inbound transport
return null;
}
-
+
/**
- * Gets the user's session, if there is one.
+ * Gets an ID generator which may be used for SAML assertions, requests, etc.
*
- * @param inTransport current inbound transport
+ * @param generator an ID generator which may be used for SAML assertions, requests, etc
+ */
+ public void setIdGenerator(IdentifierGenerator generator) {
+ idGenerator = generator;
+ }
+
+ /**
+ * Sets the SAML message binding used by inbound messages.
*
- * @return user's session
+ * @param binding SAML message binding used by inbound messages
*/
- protected Session getUserSession(InTransport inTransport){
- String sessionId = getUserSessionId(inTransport);
- return getSessionManager().getSession(sessionId);
+ public void setInboundBinding(String binding) {
+ inboundBinding = binding;
}
/**
- * Gets an ID generator which may be used for SAML assertions, requests, etc.
+ * Sets all the SAML message decoders configured for the IdP indexed by SAML binding URI.
*
- * @param generator an ID generator which may be used for SAML assertions, requests, etc
+ * @param decoders SAML message decoders configured for the IdP indexed by SAML binding URI
*/
- public void setIdGenerator(IdentifierGenerator generator) {
- idGenerator = generator;
+ public void setMessageDecoders(Map<String, SAMLMessageDecoder> decoders) {
+ messageDecoders = decoders;
}
/**
- * Sets the decoder used to extract message information from the inbound transport.
+ * Sets all the SAML message encoders configured for the IdP indexed by SAML binding URI.
*
- * @param decoder decoder used to extract message information from the inbound transport
+ * @param encoders SAML message encoders configured for the IdP indexed by SAML binding URI
*/
- public void setMessageDecoder(SAMLMessageDecoder decoder) {
- messageDecoder = decoder;
+ public void setMessageEncoders(Map<String, SAMLMessageEncoder> encoders) {
+ messageEncoders = encoders;
}
/**
- * Sets the encoder used to bind information to the outbound message transport.
+ * Sets the SAML message bindings that may be used by outbound messages.
*
- * @param encoder encoder used to bind information to the outbound message transport
+ * @param bindings SAML message bindings that may be used by outbound messages
*/
- public void setMessageEncoder(SAMLMessageEncoder encoder) {
- messageEncoder = encoder;
+ public void setSupportedOutboundBindings(List<String> bindings) {
+ supportedOutboundBindings = bindings;
+ }
+
+ /**
+ * Encodes the request's SAML response and writes it to the servlet response.
+ *
+ * @param requestContext current request context
+ *
+ * @throws ProfileException thrown if no message encoder is registered for this profiles binding
+ */
+ protected void encodeResponse(BaseSAMLProfileRequestContext requestContext) throws ProfileException {
+ if (log.isDebugEnabled()) {
+ log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
+ + " from relying party " + requestContext.getPeerEntityId());
+ }
+
+ try {
+ SAMLMessageEncoder encoder = getMessageEncoders().get(requestContext.getPeerEntityEndpoint().getBinding());
+ if (encoder == null) {
+ throw new ProfileException("No outbound message encoder configured for binding "
+ + requestContext.getPeerEntityEndpoint().getBinding());
+ }
+ requestContext.setMessageEncoder(encoder);
+ encoder.encode(requestContext);
+ } catch (MessageEncodingException e) {
+ throw new ProfileException("Unable to encode response to relying party: "
+ + requestContext.getPeerEntityId(), e);
+ }
+ }
+
+ /**
+ * Writes an aduit log entry indicating the successful response to the attribute request.
+ *
+ * @param context current request context
+ */
+ protected void writeAuditLogEntry(BaseSAMLProfileRequestContext context) {
+ AuditLogEntry auditLogEntry = new AuditLogEntry();
+ auditLogEntry.setMessageProfile(getProfileId());
+ auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
+ auditLogEntry.setPrincipalName(context.getPrincipalName());
+ auditLogEntry.setAssertingPartyId(context.getLocalEntityId());
+ auditLogEntry.setRelyingPartyId(context.getPeerEntityId());
+ auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
+ auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
+ auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
+ auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
+ if (context.getReleasedAttributes() != null) {
+ auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
+ }
+ getAduitLog().log(Level.CRITICAL, auditLogEntry);
}
}
\ No newline at end of file
assertion.setID(getIdGenerator().generateIdentifier());
assertion.setIssueInstant(issueInstant);
assertion.setVersion(SAMLVersion.VERSION_11);
- assertion.setIssuer(requestContext.getAssertingPartyEntityId());
+ assertion.setIssuer(requestContext.getLocalEntityId());
Conditions conditions = buildConditions(requestContext, issueInstant);
assertion.setConditions(conditions);
protected NameIdentifier buildNameId(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext)
throws ProfileException {
if (log.isDebugEnabled()) {
- log.debug("Building assertion NameIdentifier to relying party " + requestContext.getRelyingPartyEntityId()
+ log.debug("Building assertion NameIdentifier to relying party " + requestContext.getPeerEntityId()
+ " for principal " + requestContext.getPrincipalName());
}
Map<String, BaseAttribute> principalAttributes = requestContext.getPrincipalAttributes();
try {
if (log.isDebugEnabled()) {
log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
- + " of SAML request from relying party " + requestContext.getRelyingPartyEntityId());
+ + " of SAML request from relying party " + requestContext.getPeerEntityId());
}
Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
requestContext.setAttributes(principalAttributes);
} catch (AttributeRequestException e) {
log.error("Error resolving attributes for SAML request from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
throw new ProfileException("Error resolving attributes for SAML request from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
}
}
if (log.isDebugEnabled()) {
log.debug("Creating attribute statement in response to SAML request from relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
if (log.isDebugEnabled()) {
log.debug("Resolving principal name for subject of SAML request from relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
try {
requestContext.setPrincipalName(principal);
} catch (AttributeRequestException e) {
log.error("Error resolving attributes for SAML request from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
"Error resolving principal"));
throw new ProfileException("Error resolving attributes for SAML request from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
}
}
protected void signAssertion(BaseSAML1ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
throws ProfileException {
if (log.isDebugEnabled()) {
- log.debug("Determining if SAML assertion to relying party " + requestContext.getRelyingPartyEntityId()
+ log.debug("Determining if SAML assertion to relying party " + requestContext.getPeerEntityId()
+ " should be signed");
}
if (ssoDescriptor.getWantAssertionsSigned() != null) {
signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
if (log.isDebugEnabled()) {
- log.debug("Entity metadata for relying party " + requestContext.getRelyingPartyEntityId()
+ log.debug("Entity metadata for relying party " + requestContext.getPeerEntityId()
+ " indicates to sign assertions: " + signAssertion);
}
}
if (log.isDebugEnabled()) {
log.debug("Determining signing credntial for assertion to relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
Credential signatureCredential = profileConfig.getSigningCredential();
if (signatureCredential == null) {
}
if (log.isDebugEnabled()) {
- log.debug("Signing assertion to relying party " + requestContext.getRelyingPartyEntityId());
+ log.debug("Signing assertion to relying party " + requestContext.getPeerEntityId());
}
SAMLObjectContentReference contentRef = new SAMLObjectContentReference(assertion);
Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
Signer.signObject(signature);
}
-
- /**
- * Writes an aduit log entry indicating the successful response to the attribute request.
- *
- * @param context current request context
- */
- protected void writeAuditLogEntry(BaseSAML1ProfileRequestContext<?, ?, ?> context) {
- AuditLogEntry auditLogEntry = new AuditLogEntry();
- auditLogEntry.setMessageProfile(getProfileId());
- auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
- auditLogEntry.setPrincipalName(context.getPrincipalName());
- auditLogEntry.setAssertingPartyId(context.getAssertingPartyEntityId());
- auditLogEntry.setRelyingPartyId(context.getRelyingPartyEntityId());
- auditLogEntry.setRequestBinding(getMessageDecoder().getBindingURI());
- auditLogEntry.setRequestId(null);
- auditLogEntry.setResponseBinding(getMessageEncoder().getBindingURI());
- auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
- if (context.getReleasedAttributes() != null) {
- auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
- }
- getAduitLog().log(Level.CRITICAL, auditLogEntry);
- }
}
\ No newline at end of file
import java.util.ArrayList;
import org.apache.log4j.Logger;
+import org.opensaml.common.binding.BasicEndpointSelector;
+import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml1.core.AttributeQuery;
import org.opensaml.saml1.core.Request;
import org.opensaml.saml1.core.Response;
import org.opensaml.saml1.core.Statement;
import org.opensaml.saml1.core.StatusCode;
+import org.opensaml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
+import org.opensaml.saml2.metadata.Endpoint;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
try {
if (requestContext.getRelyingPartyConfiguration() == null) {
log.error("SAML 1 Attribute Query profile is not configured for relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
"SAML 1 Attribute Query profile is not configured for relying party "
- + requestContext.getRelyingPartyEntityId()));
+ + requestContext.getPeerEntityId()));
samlResponse = buildErrorResponse(requestContext);
}
resolvePrincipal(requestContext);
resolveAttributes(requestContext);
-
+ requestContext.setReleasedAttributes(requestContext.getPrincipalAttributes().keySet());
+
ArrayList<Statement> statements = new ArrayList<Statement>();
statements.add(buildAttributeStatement(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches"));
encodeResponse(requestContext);
writeAuditLogEntry(requestContext);
}
-
+
/**
* Decodes an incoming request and populates a created request context with the resultant information.
*
MetadataProvider metadataProvider = getMetadataProvider();
AttributeQueryContext requestContext = new AttributeQueryContext();
- requestContext.setMessageInTransport(inTransport);
+ requestContext.setInboundMessageTransport(inTransport);
requestContext.setInboundSAMLProtocol(SAMLConstants.SAML11P_NS);
- requestContext.setMessageOutTransport(outTransport);
+ requestContext.setOutboundMessageTransport(outTransport);
requestContext.setOutboundSAMLProtocol(SAMLConstants.SAML11P_NS);
requestContext.setMetadataProvider(metadataProvider);
try {
- getMessageDecoder().decode(requestContext);
+ SAMLMessageDecoder decoder = getMessageDecoders().get(getInboundBinding());
+ if (decoder == null) {
+ throw new ProfileException("No message decoder configured for inbound binding " + getInboundBinding());
+ }
+ requestContext.setMessageDecoder(decoder);
+ decoder.decode(requestContext);
if (log.isDebugEnabled()) {
log.debug("Decoded request");
}
requestContext.setInboundSAMLMessageId(attributeRequest.getID());
requestContext.setInboundSAMLMessageIssueInstant(attributeRequest.getIssueInstant());
- String relyingPartyId = requestContext.getRelyingPartyEntityId();
+ String relyingPartyId = requestContext.getPeerEntityId();
requestContext.setPeerEntityMetadata(metadataProvider.getEntityDescriptor(relyingPartyId));
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setPeerEntityRoleMetadata(requestContext.getPeerEntityMetadata().getSPSSODescriptor(
SAMLConstants.SAML10P_NS));
RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
requestContext.setRelyingPartyConfiguration(rpConfig);
+ requestContext.setPeerEntityEndpoint(selectEndpoint(requestContext));
String assertingPartyId = requestContext.getRelyingPartyConfiguration().getProviderId();
- requestContext.setAssertingPartyEntityId(assertingPartyId);
+ requestContext.setLocalEntityId(assertingPartyId);
requestContext.setLocalEntityMetadata(metadataProvider.getEntityDescriptor(assertingPartyId));
requestContext.setLocalEntityRole(AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setLocalEntityRoleMetadata(requestContext.getLocalEntityMetadata()
} catch (MetadataProviderException e) {
log.error("Unable to locate metadata for asserting or relying party");
- requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null,
- "Error locating party metadata"));
+ requestContext
+ .setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error locating party metadata"));
throw new ProfileException("Error locating party metadata");
}
}
}
/**
- * Encodes the request's SAML response and writes it to the servlet response.
+ * Selects the appropriate endpoint for the relying party and stores it in the request context.
*
* @param requestContext current request context
*
- * @throws ProfileException thrown if no message encoder is registered for this profiles binding
+ * @return Endpoint selected from the information provided in the request context
*/
- protected void encodeResponse(AttributeQueryContext requestContext) throws ProfileException {
- if (log.isDebugEnabled()) {
- log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId());
- }
-
- try {
- getMessageEncoder().encode(requestContext);
- } catch (MessageEncodingException e) {
- throw new ProfileException("Unable to encode response to relying party: "
- + requestContext.getRelyingPartyEntityId(), e);
- }
+ protected Endpoint selectEndpoint(AttributeQueryContext requestContext) {
+ BasicEndpointSelector endpointSelector = new BasicEndpointSelector();
+ endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+ endpointSelector.setMetadataProvider(getMetadataProvider());
+ endpointSelector.setRelyingParty(requestContext.getPeerEntityMetadata());
+ endpointSelector.setRelyingPartyRole(requestContext.getPeerEntityRoleMetadata());
+ endpointSelector.setSamlRequest(requestContext.getInboundSAMLMessage());
+ endpointSelector.getSupportedIssuerBindings().addAll(getSupportedOutboundBindings());
+
+ return endpointSelector.selectEndpoint();
}
/** Basic data structure used to accumulate information as a request is being processed. */
--- /dev/null
+/*
+ * 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.saml1;
+
+import org.apache.log4j.Logger;
+import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
+import org.opensaml.ws.message.MessageContext;
+import org.opensaml.ws.message.decoder.BaseMessageDecoder;
+import org.opensaml.ws.message.decoder.MessageDecodingException;
+import org.opensaml.ws.transport.http.HTTPInTransport;
+import org.opensaml.xml.util.DatatypeHelper;
+
+import edu.internet2.middleware.shibboleth.idp.profile.saml1.ShibbolethSSOProfileHandler.ShibbolethSSORequestContext;
+
+/**
+ * Shibboleth 1.0 SSO authentication request message decoder.
+ */
+public class ShibbolethSSODecoder extends BaseMessageDecoder implements SAMLMessageDecoder {
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(ShibbolethSSODecoder.class);
+
+ /** {@inheritDoc} */
+ public String getBindingURI() {
+ return "urn:mace:shibboleth:1.0:profiles:AuthnRequest";
+ }
+
+ /** {@inheritDoc} */
+ protected void doDecode(MessageContext messageContext) throws MessageDecodingException {
+ if (!(messageContext instanceof ShibbolethSSORequestContext)) {
+ log.error("Invalid message context type, this decoder only support ShibbolethSSORequestContext");
+ throw new MessageDecodingException(
+ "Invalid message context type, this decoder only support ShibbolethSSORequestContext");
+ }
+
+ if (!(messageContext.getInboundMessageTransport() instanceof HTTPInTransport)) {
+ log.error("Invalid inbound message transport type, this decoder only support HTTPInTransport");
+ throw new MessageDecodingException(
+ "Invalid inbound message transport type, this decoder only support HTTPInTransport");
+ }
+
+ ShibbolethSSORequestContext requestContext = (ShibbolethSSORequestContext) messageContext;
+ HTTPInTransport transport = (HTTPInTransport) messageContext.getInboundMessage();
+
+ String providerId = DatatypeHelper.safeTrimOrNullString(transport.getParameter("providerId"));
+ if (providerId == null) {
+ log.error("No providerId parameter given in Shibboleth SSO authentication request.");
+ throw new MessageDecodingException(
+ "No providerId parameter given in Shibboleth SSO authentication request.");
+ }
+ requestContext.setPeerEntityId(providerId);
+
+ String shire = DatatypeHelper.safeTrimOrNullString(transport.getParameter("shire"));
+ if (shire == null) {
+ log.error("No shire parameter given in Shibboleth SSO authentication request.");
+ throw new MessageDecodingException("No shire parameter given in Shibboleth SSO authentication request.");
+ }
+ requestContext.setSpAssertionConsumerService(shire);
+
+ String target = DatatypeHelper.safeTrimOrNullString(transport.getParameter("target"));
+ if (target == null) {
+ log.error("No target parameter given in Shibboleth SSO authentication request.");
+ throw new MessageDecodingException("No target parameter given in Shibboleth SSO authentication request.");
+ }
+ requestContext.setRelayState(target);
+
+ String timeStr = DatatypeHelper.safeTrimOrNullString(transport.getParameter("time"));
+ if (timeStr != null) {
+ long time = Long.parseLong(timeStr);
+ requestContext.setTime(time);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.saml1;
+
+import java.util.List;
+
+import org.opensaml.common.binding.BasicEndpointSelector;
+import org.opensaml.saml2.metadata.Endpoint;
+import org.opensaml.xml.util.DatatypeHelper;
+
+/**
+ * An endpoint selector that may optionally take a SP-provided assertion consumer service URL, validate it against
+ * metadata, and return an endpoint based on it. If no URL is provided the {@link BasicEndpointSelector} selection is
+ * used.
+ */
+public class ShibbolethSSOEndpointSelector extends BasicEndpointSelector {
+
+ /** Assertion consumer service URL provided by SP. */
+ private String spAssertionConsumerService;
+
+ /**
+ * Gets the assertion consumer service URL provided by SP.
+ *
+ * @return assertion consumer service URL provided by SP
+ */
+ public String getSpAssertionConsumerService() {
+ return spAssertionConsumerService;
+ }
+
+ /**
+ * Sets the assertion consumer service URL provided by SP.
+ *
+ * @param acs assertion consumer service URL provided by SP
+ */
+ public void setSpAssertionConsumerService(String acs) {
+ spAssertionConsumerService = DatatypeHelper.safeTrimOrNullString(acs);
+ }
+
+ /** {@inheritDoc} */
+ public Endpoint selectEndpoint() {
+ if (spAssertionConsumerService != null) {
+ return selectEndpointByACS();
+ } else {
+ return super.selectEndpoint();
+ }
+ }
+
+ /**
+ * Selects the endpoint, from metadata, corresponding to the SP-provdided ACS URL.
+ *
+ * @return endpoint corresponding to the SP-provdided ACS URL
+ */
+ protected Endpoint selectEndpointByACS() {
+ List<Endpoint> endpoints = getRelyingPartyRole().getEndpoints();
+ if (endpoints != null) {
+ for (Endpoint endpoint : endpoints) {
+ if (endpoint.getLocation().equalsIgnoreCase(spAssertionConsumerService)
+ || endpoint.getResponseLocation().equalsIgnoreCase(spAssertionConsumerService)) {
+ return endpoint;
+ }
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.profile.saml1;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.util.ArrayList;
-import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import org.opensaml.common.SAMLObjectBuilder;
-import org.opensaml.common.binding.BasicEndpointSelector;
+import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml1.core.AuthenticationStatement;
import org.opensaml.saml1.core.Request;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.ws.message.decoder.MessageDecodingException;
+import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
/** URL of the authentication manager servlet. */
private String authenticationManagerPath;
- /** URI of SAML 1 bindings supported for outgoing message encoding. */
- private ArrayList<String> supportedOutgoingBindings;
-
/**
* Constructor.
*
* @param authnManagerPath path to the authentication manager servlet
- * @param outgoingBindings URIs of SAML 1 bindings supported for outgoing message encoding
*
* @throws IllegalArgumentException thrown if either the authentication manager path or encoding binding URI are
* null or empty
*/
- public ShibbolethSSOProfileHandler(String authnManagerPath, List<String> outgoingBindings) {
+ public ShibbolethSSOProfileHandler(String authnManagerPath) {
if (DatatypeHelper.isEmpty(authnManagerPath)) {
throw new IllegalArgumentException("Authentication manager path may not be null");
}
authenticationManagerPath = authnManagerPath;
- if (outgoingBindings == null || outgoingBindings.isEmpty()) {
- throw new IllegalArgumentException("List of supported outgoing bindings may not be empty");
- }
- supportedOutgoingBindings = new ArrayList<String>(outgoingBindings);
-
authnStatementBuilder = (SAMLObjectBuilder<AuthenticationStatement>) getBuilderFactory().getBuilder(
AuthenticationStatement.DEFAULT_ELEMENT_NAME);
HttpServletResponse httpResponse = ((HttpServletResponseAdapter) outTransport).getWrappedResponse();
HttpSession httpSession = httpRequest.getSession(true);
- LoginContext loginContext = buildLoginContext(httpRequest);
+ ShibbolethSSORequestContext requestContext = decodeRequest(inTransport, outTransport);
+ ShibbolethSSOLoginContext loginContext = requestContext.getLoginContext();
+
if (getRelyingPartyConfiguration(loginContext.getRelyingPartyId()) == null) {
log.error("Shibboleth SSO profile is not configured for relying party " + loginContext.getRelyingPartyId());
throw new ProfileException("Shibboleth SSO profile is not configured for relying party "
}
/**
+ * Decodes an incoming request and populates a created request context with the resultant information.
+ *
+ * @param inTransport inbound message transport
+ * @param outTransport outbound message transport
+ *
+ * @return the created request context
+ *
+ * @throws ProfileException throw if there is a problem decoding the request
+ */
+ protected ShibbolethSSORequestContext decodeRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport)
+ throws ProfileException {
+ HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+
+ ShibbolethSSORequestContext requestContext = new ShibbolethSSORequestContext();
+ requestContext.setInboundMessageTransport(inTransport);
+ requestContext.setOutboundMessageTransport(outTransport);
+
+ SAMLMessageDecoder decoder = getMessageDecoders().get(getInboundBinding());
+ requestContext.setMessageDecoder(decoder);
+ try {
+ decoder.decode(requestContext);
+ } catch (MessageDecodingException e) {
+ log.error("Error decoding Shibboleth SSO request", e);
+ throw new ProfileException("Error decoding Shibboleth SSO request", e);
+ } catch (SecurityPolicyException e) {
+ log.error("Shibboleth SSO request does not meet security policy requirements", e);
+ throw new ProfileException("Shibboleth SSO request does not meet security policy requirements", e);
+ }
+
+ ShibbolethSSOLoginContext loginContext = new ShibbolethSSOLoginContext();
+ loginContext.setRelyingParty(requestContext.getPeerEntityId());
+ loginContext.setSpAssertionConsumerService(requestContext.getSpAssertionConsumerService());
+ loginContext.setRelyingParty(requestContext.getRelayState());
+ loginContext.setAuthenticationEngineURL(authenticationManagerPath);
+ loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(httpRequest));
+ requestContext.setLoginContext(loginContext);
+
+ return requestContext;
+ }
+
+ /**
* Creates a response to the Shibboleth SSO and sends the user, with response in tow, back to the relying party
* after they've been authenticated.
*
ArrayList<Statement> statements = new ArrayList<Statement>();
statements.add(buildAuthenticationStatement(requestContext));
if (requestContext.getProfileConfiguration().includeAttributeStatement()) {
+ requestContext.setRequestedAttributes(requestContext.getPrincipalAttributes().keySet());
statements.add(buildAttributeStatement(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:bearer"));
}
}
/**
- * Creates a login context from the incoming HTTP request.
- *
- * @param request current HTTP request
- *
- * @return the constructed login context
- *
- * @throws ProfileException thrown if the incomming request did not contain a providerId, shire, and target
- * parameter
- */
- protected ShibbolethSSOLoginContext buildLoginContext(HttpServletRequest request) throws ProfileException {
- ShibbolethSSOLoginContext loginContext = new ShibbolethSSOLoginContext();
-
- try {
- String providerId = DatatypeHelper.safeTrimOrNullString(request.getParameter("providerId"));
- if (providerId == null) {
- log.error("No providerId parameter in Shibboleth SSO request");
- throw new ProfileException("No providerId parameter in Shibboleth SSO request");
- }
- loginContext.setRelyingParty(URLDecoder.decode(providerId, "UTF-8"));
-
- RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(providerId);
- if (rpConfig == null) {
- log.error("No relying party configuration available for " + providerId);
- throw new ProfileException("No relying party configuration available for " + providerId);
- }
- loginContext.getRequestedAuthenticationMethods().add(rpConfig.getDefaultAuthenticationMethod());
-
- String acs = DatatypeHelper.safeTrimOrNullString(request.getParameter("shire"));
- if (acs == null) {
- log.error("No shire parameter in Shibboleth SSO request");
- throw new ProfileException("No shire parameter in Shibboleth SSO request");
- }
- loginContext.setSpAssertionConsumerService(URLDecoder.decode(acs, "UTF-8"));
-
- String target = DatatypeHelper.safeTrimOrNullString(request.getParameter("target"));
- if (target == null) {
- log.error("No target parameter in Shibboleth SSO request");
- throw new ProfileException("No target parameter in Shibboleth SSO request");
- }
- loginContext.setSpTarget(URLDecoder.decode(target, "UTF-8"));
- } catch (UnsupportedEncodingException e) {
- // UTF-8 encoding required to be supported by all JVMs.
- }
-
- loginContext.setAuthenticationEngineURL(authenticationManagerPath);
- loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(request));
- return loginContext;
- }
-
- /**
* Creates an authentication request context from the current environmental information.
*
* @param loginContext current login context
requestContext.setUserSession(getUserSession(in));
requestContext.setRelayState(loginContext.getSpTarget());
- requestContext.setMessageInTransport(in);
+ requestContext.setInboundMessageTransport(in);
requestContext.setInboundSAMLProtocol(ShibbolethConstants.SHIB_SSO_PROFILE_URI);
MetadataProvider metadataProvider = getMetadataProvider();
requestContext.setMetadataProvider(metadataProvider);
String relyingPartyId = loginContext.getRelyingPartyId();
- requestContext.setRelyingPartyEntityId(relyingPartyId);
+ requestContext.setPeerEntityId(relyingPartyId);
EntityDescriptor relyingPartyMetadata = metadataProvider.getEntityDescriptor(relyingPartyId);
requestContext.setPeerEntityMetadata(relyingPartyMetadata);
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- requestContext.setPeerEntityRoleMetadata(relyingPartyMetadata
- .getSPSSODescriptor(SAMLConstants.SAML11P_NS));
+ requestContext.setPeerEntityRoleMetadata(relyingPartyMetadata.getSPSSODescriptor(SAMLConstants.SAML11P_NS));
RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
requestContext.setRelyingPartyConfiguration(rpConfig);
requestContext.setPeerEntityEndpoint(selectEndpoint(requestContext));
String assertingPartyId = rpConfig.getProviderId();
- requestContext.setAssertingPartyEntityId(assertingPartyId);
+ requestContext.setLocalEntityId(assertingPartyId);
EntityDescriptor assertingPartyMetadata = metadataProvider.getEntityDescriptor(assertingPartyId);
requestContext.setLocalEntityMetadata(assertingPartyMetadata);
requestContext.setLocalEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setLocalEntityRoleMetadata(assertingPartyMetadata
.getIDPSSODescriptor(SAMLConstants.SAML20P_NS));
- requestContext.setMessageOutTransport(out);
+ requestContext.setOutboundMessageTransport(out);
requestContext.setOutboundSAMLProtocol(SAMLConstants.SAML20P_NS);
ShibbolethSSOConfiguration profileConfig = (ShibbolethSSOConfiguration) rpConfig
.getProfileConfiguration(SSOConfiguration.PROFILE_ID);
protected Endpoint selectEndpoint(ShibbolethSSORequestContext requestContext) {
ShibbolethSSOLoginContext loginContext = requestContext.getLoginContext();
- if (loginContext.getSpAssertionConsumerService() != null) {
- SAMLObjectBuilder<AssertionConsumerService> acsBuilder = (SAMLObjectBuilder<AssertionConsumerService>) getBuilderFactory()
- .getBuilder(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
- AssertionConsumerService acsEndpoint = acsBuilder.buildObject();
- acsEndpoint.setBinding(getMessageEncoder().getBindingURI());
- acsEndpoint.setLocation(loginContext.getSpAssertionConsumerService());
- return acsEndpoint;
- }
-
- BasicEndpointSelector endpointSelector = new BasicEndpointSelector();
+ ShibbolethSSOEndpointSelector endpointSelector = new ShibbolethSSOEndpointSelector();
+ endpointSelector.setSpAssertionConsumerService(loginContext.getSpAssertionConsumerService());
endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
endpointSelector.setMetadataProvider(getMetadataProvider());
endpointSelector.setRelyingParty(requestContext.getPeerEntityMetadata());
endpointSelector.setRelyingPartyRole(requestContext.getPeerEntityRoleMetadata());
endpointSelector.setSamlRequest(requestContext.getInboundSAMLMessage());
- endpointSelector.getSupportedIssuerBindings().addAll(supportedOutgoingBindings);
+ endpointSelector.getSupportedIssuerBindings().addAll(getSupportedOutboundBindings());
+
return endpointSelector.selectEndpoint();
}
protected SubjectLocality buildSubjectLocality(ShibbolethSSORequestContext requestContext) {
SubjectLocality subjectLocality = subjectLocalityBuilder.buildObject();
- HTTPInTransport inTransport = (HTTPInTransport) requestContext.getMessageInTransport();
+ HTTPInTransport inTransport = (HTTPInTransport) requestContext.getInboundMessageTransport();
subjectLocality.setIPAddress(inTransport.getPeerAddress());
subjectLocality.setDNSAddress(inTransport.getPeerDomainName());
return subjectLocality;
}
- /**
- * Encodes the request's SAML response and writes it to the servlet response.
- *
- * @param requestContext current request context
- *
- * @throws ProfileException thrown if no message encoder is registered for this profiles binding
- */
- protected void encodeResponse(ShibbolethSSORequestContext requestContext) throws ProfileException {
- if (log.isDebugEnabled()) {
- log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId());
- }
-
- try {
- getMessageEncoder().encode(requestContext);
- } catch (MessageEncodingException e) {
- throw new ProfileException("Unable to encode response to relying party: "
- + requestContext.getRelyingPartyEntityId(), e);
- }
- }
-
/** Represents the internal state of a Shibboleth SSO Request while it's being processed by the IdP. */
- protected class ShibbolethSSORequestContext extends
+ public class ShibbolethSSORequestContext extends
BaseSAML1ProfileRequestContext<Request, Response, ShibbolethSSOConfiguration> {
+ /** Time since the epoch. */
+ private long time;
+
+ /** SP-provide assertion consumer service URL. */
+ private String spAssertionConsumerService;
+
/** Current login context. */
private ShibbolethSSOLoginContext loginContext;
public void setLoginContext(ShibbolethSSOLoginContext context) {
loginContext = context;
}
+
+ /**
+ * Gets the SP-provided assertion consumer service URL.
+ *
+ * @return SP-provided assertion consumer service URL
+ */
+ public String getSpAssertionConsumerService() {
+ return spAssertionConsumerService;
+ }
+
+ /**
+ * Sets the SP-provided assertion consumer service URL.
+ *
+ * @param acs SP-provided assertion consumer service URL
+ */
+ public void setSpAssertionConsumerService(String acs) {
+ spAssertionConsumerService = acs;
+ }
+
+ /**
+ * Sets the time since the epoch.
+ *
+ * @return time since the epoch
+ */
+ public long getTime() {
+ return time;
+ }
+
+ /**
+ * Sets the time since the epoch.
+ *
+ * @param time time since the epoch
+ */
+ public void setTime(long time) {
+ this.time = time;
+ }
}
}
\ No newline at end of file
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.SAMLVersion;
import org.opensaml.common.impl.SAMLObjectContentReference;
-import org.opensaml.log.Level;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.AttributeQuery;
import org.opensaml.saml2.core.AttributeStatement;
import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncodingException;
import edu.internet2.middleware.shibboleth.common.attribute.encoding.SAML2NameIDAttributeEncoder;
import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML2AttributeAuthority;
-import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.AbstractSAML2ProfileConfiguration;
import edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler;
protected Issuer buildEntityIssuer(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext) {
Issuer issuer = issuerBuilder.buildObject();
issuer.setFormat(Issuer.ENTITY);
- issuer.setValue(requestContext.getAssertingPartyEntityId());
+ issuer.setValue(requestContext.getLocalEntityId());
return issuer;
}
if (log.isDebugEnabled()) {
log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
+ " of SAML request " + requestContext.getInboundSAMLMessageId() + " from relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
Map<String, BaseAttribute> principalAttributes = attributeAuthority.getAttributes(requestContext);
requestContext.setAttributes(principalAttributes);
} catch (AttributeRequestException e) {
log.error("Error resolving attributes for SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId(), e);
+ + " from relying party " + requestContext.getPeerEntityId(), e);
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null, "Error resolving attributes"));
throw new ProfileException("Error resolving attributes for SAML request "
+ requestContext.getInboundSAMLMessageId() + " from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
}
}
if (log.isDebugEnabled()) {
log.debug("Creating attribute statement in response to SAML request "
+ requestContext.getInboundSAMLMessageId() + " from relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
AbstractSAML2ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
SAML2AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
AbstractSAML2ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
if (profileConfiguration == null) {
log.error("Unable to resolve principal, no SAML 2 profile configuration for relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.REQUEST_DENIED_URI,
"Error resolving principal"));
throw new ProfileException(
"Unable to resolve principal, no SAML 2 profile configuration for relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
SAML2AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
if (log.isDebugEnabled()) {
log.debug("Resolving principal name for subject of SAML request "
+ requestContext.getInboundSAMLMessageId() + " from relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
try {
requestContext.setPrincipalName(principal);
} catch (AttributeRequestException e) {
log.error("Error resolving attributes for SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId(), e);
+ + " from relying party " + requestContext.getPeerEntityId(), e);
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.UNKNOWN_PRINCIPAL_URI,
"Error resolving principal"));
throw new ProfileException("Error resolving attributes for SAML request "
+ requestContext.getInboundSAMLMessageId() + " from relying party "
- + requestContext.getRelyingPartyEntityId(), e);
+ + requestContext.getPeerEntityId(), e);
}
}
protected void signAssertion(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext, Assertion assertion)
throws ProfileException {
if (log.isDebugEnabled()) {
- log.debug("Determining if SAML assertion to relying party " + requestContext.getRelyingPartyEntityId()
+ log.debug("Determining if SAML assertion to relying party " + requestContext.getPeerEntityId()
+ " should be signed");
}
if (ssoDescriptor.getWantAssertionsSigned() != null) {
signAssertion = ssoDescriptor.getWantAssertionsSigned().booleanValue();
if (log.isDebugEnabled()) {
- log.debug("Entity metadata for relying party " + requestContext.getRelyingPartyEntityId()
+ log.debug("Entity metadata for relying party " + requestContext.getPeerEntityId()
+ " indicates to sign assertions: " + signAssertion);
}
}
if (log.isDebugEnabled()) {
log.debug("Determining signing credntial for assertion to relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
}
Credential signatureCredential = profileConfig.getSigningCredential();
if (signatureCredential == null) {
}
if (log.isDebugEnabled()) {
- log.debug("Signing assertion to relying party " + requestContext.getRelyingPartyEntityId());
+ log.debug("Signing assertion to relying party " + requestContext.getPeerEntityId());
}
SAMLObjectContentReference contentRef = new SAMLObjectContentReference(assertion);
Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
// TODO handle encryption
SubjectConfirmationData confirmationData = subjectConfirmationDataBuilder.buildObject();
- HTTPInTransport inTransport = (HTTPInTransport) requestContext.getMessageInTransport();
+ HTTPInTransport inTransport = (HTTPInTransport) requestContext.getInboundMessageTransport();
confirmationData.setAddress(inTransport.getPeerAddress());
confirmationData.setInResponseTo(requestContext.getInboundSAMLMessageId());
confirmationData.setNotOnOrAfter(issueInstant.plus(requestContext.getProfileConfiguration()
protected NameID buildNameId(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
if (log.isDebugEnabled()) {
log.debug("Building assertion NameID for principal/relying party:" + requestContext.getPrincipalName()
- + "/" + requestContext.getRelyingPartyEntityId());
+ + "/" + requestContext.getPeerEntityId());
}
Map<String, BaseAttribute> principalAttributes = requestContext.getPrincipalAttributes();
List<String> supportedNameFormats = getNameFormats(requestContext);
return samlResponse;
}
-
- /**
- * Writes an aduit log entry indicating the successful response to the attribute request.
- *
- * @param context current request context
- */
- protected void writeAuditLogEntry(BaseSAML2ProfileRequestContext<?, ?, ?> context) {
- AuditLogEntry auditLogEntry = new AuditLogEntry();
- auditLogEntry.setMessageProfile(getProfileId());
- auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
- auditLogEntry.setPrincipalName(context.getPrincipalName());
- auditLogEntry.setAssertingPartyId(context.getAssertingPartyEntityId());
- auditLogEntry.setRelyingPartyId(context.getRelyingPartyEntityId());
- auditLogEntry.setRequestBinding(getMessageDecoder().getBindingURI());
- auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
- auditLogEntry.setResponseBinding(getMessageEncoder().getBindingURI());
- auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
- if (context.getReleasedAttributes() != null) {
- auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
- }
- getAduitLog().log(Level.CRITICAL, auditLogEntry);
- }
}
\ No newline at end of file
import java.util.ArrayList;
import org.apache.log4j.Logger;
+import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.AttributeQuery;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
try {
if (requestContext.getRelyingPartyConfiguration() == null) {
log.error("SAML 2 Attribute Query profile is not configured for relying party "
- + requestContext.getRelyingPartyEntityId());
+ + requestContext.getPeerEntityId());
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.REQUEST_DENIED_URI,
"SAML 2 Attribute Query profile is not configured for relying party "
- + requestContext.getRelyingPartyEntityId()));
+ + requestContext.getPeerEntityId()));
samlResponse = buildErrorResponse(requestContext);
}
// Resolve attribute query name id to principal name and place in context
resolvePrincipal(requestContext);
-
resolveAttributes(requestContext);
+ requestContext.setReleasedAttributes(requestContext.getPrincipalAttributes().keySet());
// Lookup principal name and attributes, create attribute statement from information
ArrayList<Statement> statements = new ArrayList<Statement>();
MetadataProvider metadataProvider = getMetadataProvider();
AttributeQueryContext requestContext = new AttributeQueryContext();
- requestContext.setMessageInTransport(inTransport);
+ requestContext.setInboundMessageTransport(inTransport);
requestContext.setInboundSAMLProtocol(SAMLConstants.SAML20P_NS);
- requestContext.setMessageOutTransport(outTransport);
+ requestContext.setOutboundMessageTransport(outTransport);
requestContext.setOutboundSAMLProtocol(SAMLConstants.SAML20P_NS);
requestContext.setMetadataProvider(metadataProvider);
try {
- getMessageDecoder().decode(requestContext);
+ SAMLMessageDecoder decoder = getMessageDecoders().get(getInboundBinding());
+ requestContext.setMessageDecoder(decoder);
+ decoder.decode(requestContext);
if (log.isDebugEnabled()) {
log.debug("Decoded request");
}
requestContext.setInboundSAMLMessageId(attributeQuery.getID());
requestContext.setInboundSAMLMessageIssueInstant(attributeQuery.getIssueInstant());
- String relyingPartyId = requestContext.getRelyingPartyEntityId();
+ String relyingPartyId = requestContext.getPeerEntityId();
requestContext.setPeerEntityMetadata(metadataProvider.getEntityDescriptor(relyingPartyId));
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setPeerEntityRoleMetadata(requestContext.getPeerEntityMetadata().getSPSSODescriptor(
requestContext.setRelyingPartyConfiguration(rpConfig);
String assertingPartyId = requestContext.getRelyingPartyConfiguration().getProviderId();
- requestContext.setAssertingPartyEntityId(assertingPartyId);
+ requestContext.setLocalEntityId(assertingPartyId);
requestContext.setLocalEntityMetadata(metadataProvider.getEntityDescriptor(assertingPartyId));
requestContext.setLocalEntityRole(AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setLocalEntityRoleMetadata(requestContext.getLocalEntityMetadata()
}
}
- /**
- * Encodes the request's SAML response and writes it to the servlet response.
- *
- * @param requestContext current request context
- *
- * @throws ProfileException thrown if no message encoder is registered for this profiles binding
- */
- protected void encodeResponse(AttributeQueryContext requestContext) throws ProfileException {
- if (log.isDebugEnabled()) {
- log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId());
- }
-
- try {
- getMessageEncoder().encode(requestContext);
- } catch (MessageEncodingException e) {
- throw new ProfileException("Unable to encode response to relying party: "
- + requestContext.getRelyingPartyEntityId(), e);
- }
- }
-
/** Basic data structure used to accumulate information as a request is being processed. */
protected class AttributeQueryContext extends
BaseSAML2ProfileRequestContext<AttributeQuery, Response, AttributeQueryConfiguration> {
import org.apache.log4j.Logger;
import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.binding.AuthnResponseEndpointSelector;
import org.opensaml.saml2.core.AuthnContext;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
try {
SSORequestContext requestContext = decodeRequest(inTransport, outTransport);
- String relyingPartyId = requestContext.getRelyingPartyEntityId();
+ String relyingPartyId = requestContext.getPeerEntityId();
RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
if (rpConfig == null) {
log.error("No relying party configuration for " + relyingPartyId);
ArrayList<Statement> statements = new ArrayList<Statement>();
statements.add(buildAuthnStatement(requestContext));
if (requestContext.getProfileConfiguration().includeAttributeStatement()) {
+ requestContext.setRequestedAttributes(requestContext.getPrincipalAttributes().keySet());
statements.add(buildAttributeStatement(requestContext));
}
}
SSORequestContext requestContext = new SSORequestContext();
- requestContext.setMessageInTransport(inTransport);
- requestContext.setMessageOutTransport(outTransport);
+ requestContext.setInboundMessageTransport(inTransport);
+ requestContext.setOutboundMessageTransport(outTransport);
requestContext.setMetadataProvider(getMetadataProvider());
try {
- getMessageDecoder().decode(requestContext);
+ SAMLMessageDecoder decoder = getMessageDecoders().get(getInboundBinding());
+ requestContext.setMessageDecoder(decoder);
+ decoder.decode(requestContext);
return requestContext;
} catch (MessageDecodingException e) {
log.error("Error decoding authentication request message", e);
requestContext.setUserSession(getUserSession(in));
requestContext.setRelayState(loginContext.getRelayState());
- requestContext.setMessageInTransport(in);
+ requestContext.setInboundMessageTransport(in);
requestContext.setInboundSAMLProtocol(SAMLConstants.SAML20P_NS);
requestContext.setInboundMessage(loginContext.getAuthenticationRequest());
requestContext.setInboundSAMLMessage(loginContext.getAuthenticationRequest());
requestContext.setMetadataProvider(metadataProvider);
String relyingPartyId = loginContext.getRelyingPartyId();
- requestContext.setRelyingPartyEntityId(relyingPartyId);
+ requestContext.setPeerEntityId(relyingPartyId);
EntityDescriptor relyingPartyMetadata = metadataProvider.getEntityDescriptor(relyingPartyId);
requestContext.setPeerEntityMetadata(relyingPartyMetadata);
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- requestContext.setPeerEntityRoleMetadata(relyingPartyMetadata
- .getSPSSODescriptor(SAMLConstants.SAML20P_NS));
+ requestContext.setPeerEntityRoleMetadata(relyingPartyMetadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS));
RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
requestContext.setRelyingPartyConfiguration(rpConfig);
requestContext.setPeerEntityEndpoint(selectEndpoint(requestContext));
String assertingPartyId = rpConfig.getProviderId();
- requestContext.setAssertingPartyEntityId(assertingPartyId);
+ requestContext.setLocalEntityId(assertingPartyId);
EntityDescriptor assertingPartyMetadata = metadataProvider.getEntityDescriptor(assertingPartyId);
requestContext.setLocalEntityMetadata(assertingPartyMetadata);
requestContext.setLocalEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
requestContext.setLocalEntityRoleMetadata(assertingPartyMetadata
.getIDPSSODescriptor(SAMLConstants.SAML20P_NS));
- requestContext.setMessageOutTransport(out);
+ requestContext.setOutboundMessageTransport(out);
requestContext.setOutboundSAMLProtocol(SAMLConstants.SAML20P_NS);
SSOConfiguration profileConfig = (SSOConfiguration) rpConfig
.getProfileConfiguration(SSOConfiguration.PROFILE_ID);
* @return subject locality for the authentication statement
*/
protected SubjectLocality buildSubjectLocality(SSORequestContext requestContext) {
- HTTPInTransport transport = (HTTPInTransport) requestContext.getMessageInTransport();
+ HTTPInTransport transport = (HTTPInTransport) requestContext.getInboundMessageTransport();
SubjectLocality subjectLocality = subjectLocalityBuilder.buildObject();
subjectLocality.setAddress(transport.getPeerAddress());
subjectLocality.setDNSName(transport.getPeerDomainName());
return endpointSelector.selectEndpoint();
}
- /**
- * Encodes the request's SAML response and writes it to the servlet response.
- *
- * @param requestContext current request context
- *
- * @throws ProfileException thrown if no message encoder is registered for this profiles binding
- */
- protected void encodeResponse(SSORequestContext requestContext) throws ProfileException {
- if (log.isDebugEnabled()) {
- log.debug("Encoding response to SAML request " + requestContext.getInboundSAMLMessageId()
- + " from relying party " + requestContext.getRelyingPartyEntityId());
- }
-
- try {
- getMessageEncoder().encode(requestContext);
- } catch (MessageEncodingException e) {
- throw new ProfileException("Unable to encode response to relying party: "
- + requestContext.getRelyingPartyEntityId(), e);
- }
- }
-
/** Represents the internal state of a SAML 2.0 SSO Request while it's being processed by the IdP. */
protected class SSORequestContext extends BaseSAML2ProfileRequestContext<AuthnRequest, Response, SSOConfiguration> {