Page tree
Skip to end of metadata
Go to start of metadata

File(s): conf/idp.propertiesconf/relying-party.xml, conf/cas-protocol.xml

Format: Native Spring


Shibboleth IdP 3.0 supports most of the CAS protocol v2 specification including attribute release and CAS proxy support.

Notable features:

  1. The XML response delivered by the /serviceValidate URI includes the <cas:attributes> extension supported by most CAS clients.

  2. CAS proxy support with SSL/TLS trust configuration provided by Shibboleth IdP trust engine.
  3. Simple metadata facility to configure verified relying parties modeled on Jasig/Apereo CAS service registry.

Notable requirements:

The CAS protocol requires a server-side StorageService implementation for both the CAS protocol ticket store and IdP session store. The following storage service implementations are suitable for use with CAS:

  • MemoryStorageService (shibboleth.StorageService bean)
  • JPAStorageService (HA compatible)
  • MemcachedStorageService (HA compatible)

Notable limitations:

There is no support at present for the CAS /logout URI since global logout/single logout (SLO) in Shibboleth has been discouraged historically. IdP 3.0 has improved support for IdP-initiated SLO, which is conceptually similar to the behavior of the CAS /logout URI, and will be implemented on top of IdP capabilities in 3.2.0 (tentative).

CAS Quickstart

  1. Configure suitable storage service.
  2. Add CAS protocol profiles to the default relying party by editing conf/relying-party.xml.
  3. Add verified CAS relying parties by editing conf/cas-protocol.xml.

  4. Configure SSL/TLS trust (optional; only required for CAS proxy support).

Configure Storage Service

CAS requires a server-side storage service for CAS protocol tickets and IdP sessions since the ticket validation step of the protocol requires back-channel communication. The following properties define the storage service used for IdP sessions and CAS tickets, respectively:

  • idp.session.StorageService
  • idp.cas.StorageService

Modify conf/idp.properties accordingly to define suitable storage service beans for each subsystem. For simple deployments, the default in-memory storage service bean, shibboleth.StorageService, should suffice. HA deployments will require defining a custom JPAStorageService or MemcachedStorageService bean in conf/global.xml and referencing that.

Sample idp.properties excerpt for CAS
# Simple non-HA deployment case
idp.session.StorageService=shibboleth.StorageService
idp.cas.StorageService=shibboleth.StorageService

Enable CAS Protocol

The CAS protocol support is represented with a set of profile configuration beans, one for each of the primary CAS protocol URIs:

Profile Bean NameURI Path
CAS.LoginConfiguration/login
CAS.ProxyConfiguration/proxy
CAS.ValidateConfiguration/serviceValidate, /proxyValidate, /samlValidate

Each deals with configuration concerns around the related URI. The profiles are enabled as a function of relying party or relying party group as described in Profiles and Per-RelyingParty Behavior. While each profile may be enabled individually, the only configuration that provides meaningful behavior is one that includes at least CAS.LoginConfiguration and CAS.ValidateConfiguration. The CAS.ProxyConfiguration profile bean is truly optional since omitting it disables proxy support for the relying party, which is a meaningful configuration capability. The following configuration example demonstrates how to enable all CAS protocols  for the default relying party.

CAS enabled for default relying party
<bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
    <property name="profileConfigurations">
        <list>
            <ref bean="Shibboleth.SSO" />
            <ref bean="SAML1.AttributeQuery" />
            <ref bean="SAML1.ArtifactResolution" />
            <ref bean="SAML2.SSO" />
            <ref bean="SAML2.ECP" />
            <ref bean="SAML2.Logout" />
            <ref bean="SAML2.AttributeQuery" />
            <ref bean="SAML2.ArtifactResolution" />
            <ref bean="CAS.LoginConfiguration" />
            <ref bean="CAS.ProxyConfiguration" />
            <ref bean="CAS.ValidateConfiguration" />
        </list>
    </property>
</bean> 

Define Relying Party Metadata in the Service Registry

Relying parties that authenticate to the IdP via the CAS protocol are called "services." CAS services don't have any of the configuration concerns of a SAML relying party, but there is a need to define peer entities and related metadata all the same. The service registry provides a CAS analogue to SAML metadata. A CAS service is verified in the relying party sense if there exists a definition for it in the CAS service registry. Verified relying parties are defined by regular expressions that describe the URL of the CAS service requesting a ticket. Regular expressions are used since a single logical group of services may consist of a number of related URIs, any of which may request CAS tickets. In the world of institutional SSO where CAS has thrived, it's common to permit SSO for all HTTPS services within the DNS domain of the institution; in that case an expression like the following might be used:

https:\/\/([A-Za-z0-9_-]+\.)*example\.org(:\d+)?\/.*

The "unverified" relying party configuration applies to CAS services that have no matching service registry entry, and it is common to have the CAS protocol disabled for unverified relying parties. The net result is one familiar to existing CAS adopters: unregistered services cannot participate in CAS SSO.

Registered services are configured via the cas.serviceRegistry bean in conf/cas-protocol.xml. The following configuration snippet provides an example.

<bean id="cas.serviceRegistry"
      class="net.shibboleth.idp.cas.service.PatternServiceRegistry">
    <property name="definitions">
        <list>
            <bean class="net.shibboleth.idp.cas.service.ServiceDefinition"
                  c:regex="https:\/\/([A-Za-z0-9_-]+\.)*example\.org(:\d+)?\/.*"
                  p:group="institutional-services"
                  p:authorizedToProxy="false" />
        </list>
    </property>
</bean>

The fields of ServiceDefinition are straightforward:

  1. regex - regular expression that defines the logical set of services, by endpoint URI, that belong to the group
  2. group - human-readable name of the group of services
  3. authorizedToProxy - whether members of the group are authorized to request CAS proxy tickets

It's worth noting that the authorizedToProxy flag provides a fine-grained proxy authorization control that interacts with the CAS.ProxyConfiguration profile bean. The flag only applies when the proxy profile is enabled for the affected relying party; in that case proxying may be enabled on a per-service group basis. If proxying is disabled for the relying party, authorizedToProxy=true has no effect.

Service Definition Order

The order in which service definitions appear in PatternServiceRegistry determines the evaluation order when a CAS service attempts authentication. If two definitions match an overlapping set of services, the first one to produce a match wins. In general, service definitions with more specific patterns should precede those with more general patterns.

Configure Proxy Trust (Optional)

The IdP uses the PKIX trust model to validate a service that requests a proxy ticket. When the service provides a pgtUrl protocol parameter at ticket validation time, the IdP attempts an HTTP connection to that URL. (The IdP will immediately reject a non-HTTPS proxy callback URL.) Note that the URL is not necessarily the same as that of the requesting service; they are logically separate to allow configuration of different certificate credentials (among other reasons). The proxy callback endpoint must present a certificate that is trusted by the IdP, which requires explicit configuration. The IdP does not use the default Java truststore for this purpose since that would not provide adequate security. The IdP configuration machinery for proxy trust is designed to force deployers to consider what hosts they trust. While this approach requires more effort, it provides the additional security intended for proxy validation.

There are two approaches to proxy trust configuration:

  1. List the end-entity certificates of the hosts that are permitted to proxy.
  2. List the issuer certificates of hosts that are permitted to proxy.

The second approach only provides meaningful security when you have a small number of certificate authorities that issue Web server certificates with a high degree of identity vetting. If that requirement is not met, configuring end-entity certificates is the recommended approach, but it obviously comes at the cost of additional maintenance as certificates are replaced on the proxying endpoints.

CAS proxy trust is configured in relying-party.xml as part of the profile configuration for a particular relying party. The following configuration excerpt demonstrates configuring CAS to accept proxy callback certificates issued by a handful of trusted issuers for the default relying party.

CAS Proxy Trust in relying-party.xml
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
        <property name="profileConfigurations">
            <list>
                <ref bean="Shibboleth.SSO" />
                <ref bean="SAML1.AttributeQuery" />
                <ref bean="SAML1.ArtifactResolution" />
                <ref bean="SAML2.SSO" />
                <ref bean="SAML2.ECP" />
                <ref bean="SAML2.Logout" />
                <ref bean="SAML2.AttributeQuery" />
                <ref bean="SAML2.ArtifactResolution" />
                <ref bean="CAS.LoginConfiguration" />
                <ref bean="CAS.ProxyConfiguration" />
                <ref bean="CAS.ValidateConfiguration.default" />
            </list>
        </property>
    </bean>
    <bean id="CAS.ValidateConfiguration.default" parent="CAS.ValidateConfiguration">
        <property name="securityConfiguration">
            <bean class="net.shibboleth.idp.profile.config.SecurityConfiguration"
                  c:skew="PT5M"
                  p:clientTLSValidationConfiguration-ref="standardProxyTLSConfig">
                <constructor-arg name="generator">
                    <bean class="net.shibboleth.idp.cas.ticket.impl.TicketIdentifierGenerationStrategy"
                          c:prefix="PGT"
                          c:randomLength="50" />
                </constructor-arg>
            </bean>
        </property>
    </bean>
    <bean id="standardProxyTLSConfig"
          class="org.opensaml.security.x509.tls.impl.BasicClientTLSValidationConfiguration">
        <property name="x509TrustEngine">
            <bean class="org.opensaml.security.x509.impl.PKIXX509CredentialTrustEngine" c:nameEvaluator="#{null}">
                <constructor-arg name="resolver">
                    <bean class="org.opensaml.security.x509.impl.StaticPKIXValidationInformationResolver" c:names="#{null}">
                        <constructor-arg name="info">
                            <bean class="org.opensaml.security.x509.impl.BasicPKIXValidationInformation" c:crls="#{null}" c:depth="5">
                                <constructor-arg name="anchors">
                                    <list>
                                        <bean class="net.shibboleth.ext.spring.factory.X509CertificateFactoryBean"
                                              p:resource="%{idp.home}/credentials/vtgsca.pem" />
                                        <bean class="net.shibboleth.ext.spring.factory.X509CertificateFactoryBean"
                                              p:resource="%{idp.home}/credentials/vtgqsca.pem" />
                                        <bean class="net.shibboleth.ext.spring.factory.X509CertificateFactoryBean"
                                              p:resource="%{idp.home}/credentials/vtgqsca256.pem" />
                                    </list>
                                </constructor-arg>
                            </bean>
                        </constructor-arg>
                    </bean>
                </constructor-arg>
                <constructor-arg name="pkixEvaluator">
                    <bean class="org.opensaml.security.x509.impl.CertPathPKIXTrustEvaluator" />
                </constructor-arg>
            </bean>
        </property>
    </bean>

Service Ticket Expiration (Optional)

CAS Service tickets issued by the Shibboleth IdP are single use tickets with a default validity period of 15 seconds. It is possible to extend the validity period by altering the profile configuration in relying-party.xml as follows:

    <!-- Default configuration, with default settings applied for all profiles. -->
    <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
        <property name="profileConfigurations">
            <list>
                <ref bean="Shibboleth.SSO.default" />
                <!-- ... other SAML profiles ... -->
                <bean parent="CAS.LoginConfiguration" p:ticketValidityPeriod="PT5M" />
                <ref bean="CAS.ProxyConfiguration" />
                <ref bean="CAS.ValidateConfiguration.default" />
            </list>
        </property>
    </bean>

Alternate cas:user in the validation response (Optional)

CAS validation responses include the user's username. This is generally the normalized username the user logged in with. It is possible to substitute the username in the response with a value from another IdP attribute using the p:userAttribute attribute of CAS.ValidateConfiguration profile in a Relying Party Override.

In this example, 3 services will get the value of the studentId attribute instead of the standard username. Note that these services are identified by Regex strings instead of standard literal strings.

<util:list id="shibboleth.RelyingPartyOverrides">
		<bean id="shibboleth.regexRelyingParty" parent="RelyingParty" >
			<property name="activationCondition" >
				<bean class="net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate" >
					<constructor-arg name="pred" >
						<bean class="com.google.common.base.Predicates" factory-method="or" >
							<constructor-arg>
								<util:list>
									<bean class="com.google.common.base.Predicates" factory-method="containsPattern"
										c:_0="https://example1\.org\/service1\/.*" />
									<bean class="com.google.common.base.Predicates" factory-method="containsPattern"
										c:_0="https://example2\.org\/service2\/.*" />
									<bean class="com.google.common.base.Predicates" factory-method="containsPattern"
										c:_0="https://example3\.org\/service3\/.*" />
								</util:list>
							</constructor-arg>
						</bean>
					</constructor-arg>
				</bean>
			</property>
			<property name="profileConfigurations">
				<list>
					<ref bean="CAS.LoginConfiguration" />
					<ref bean="CAS.ProxyConfiguration" />
					<bean parent="CAS.ValidateConfiguration" p:userAttribute="studentId" />
				</list>
    		</property>	
	    </bean>
	</util:list>


External client configuration

As CAS is configured as a new profile for the default relying party, CAS clients should be configured with these values

PropertyValue
$cas_hostidp.example.org
$cas_context/idp/profile/cas

This example is based on PHP CAS Client from Jasig.

  • No labels