Shibboleth-CAS Integration
Outline
CAS can be integrated with the Shibboleth federated SSO platform by a couple different strategies.Designate CAS the Authentication Provider for Shib IDP
The following instructions describe how to set up a recent CAS server (e.g. 3.3.x) to serve as the authentication provider for the Shibboleth 2.x IDP. With such a setup, when user is routed to the Shib IDP, one of two things will happen:
- If the user has already authenticated to CAS and has a valid CAS SSO session, the IDP will transparently perform the requested action, e.g. attribute release.
- If the user does not have a valid CAS SSO session, the user will be redirected to CAS and must authenticate before the IDP proceeds with the requested action.
CAS-Shib IDP integration in this manner is well supported and straightforward to implement.
Instructions
Before you begin, you should give some thought to configuration management issues. Although the steps below could be implemented by simply copying files and editing configuration XML in the deployed IDP war file directory, the Middleware Group at Virginia Tech has found it much easier to develop an ant-based build process that overlays configuration files on top of the ant-based IDP build. That has worked out well for us and has greatly eased the process by which configuration changes are tested and deployed.
Include CAS Client Libraries in IDP Deployable
Download the latest Jasig Java CAS Client Release and modify the IDP war deployable such that the following jars are included in the ./lib installer folder, then run ./install.sh to build and deploy with these files:
cas-client-$VERSION/modules/cas-client-core-$VERSION.jar cas-client-$VERSION/modules/commons-logging-$VERSION.jar
Note that commons-logging is, in fact, required since Shib uses slf4j for logging. If in the future the CAS client switches to slf4j, commons-logging will not be needed.
Modify $SHIB_HOME/conf/handler.xml
Define the RemoteUser
authentication method to be used with CAS authentication.
<!-- Remote User handler for CAS support --> <LoginHandler xsi:type="RemoteUser"> <AuthenticationMethod> urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified </AuthenticationMethod> <AuthenticationMethod> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </AuthenticationMethod> </LoginHandler>
Modify IDP Deployable web.xml
Add the following XML blocks to the web.xml file for the IDP war deployable. Replace Ant placeholder properties with values appropriate to your environment.
<!-- For CAS client support --> <context-param> <param-name>serverName</param-name> <param-value>${idp.hostname}</param-value> </context-param>
<!-- CAS client filters --> <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class> org.jasig.cas.client.authentication.AuthenticationFilter </filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>${cas.server.url}login</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/Authn/RemoteUser</url-pattern> </filter-mapping> <filter> <filter-name>CAS Validation Filter</filter-name> <filter-class> org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter </filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>${cas.server.url}</param-value> </init-param> <init-param> <param-name>redirectAfterValidation</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/Authn/RemoteUser</url-pattern> </filter-mapping> <filter> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <filter-class> org.jasig.cas.client.util.HttpServletRequestWrapperFilter </filter-class> </filter> <filter-mapping> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <url-pattern>/Authn/RemoteUser</url-pattern> </filter-mapping>
The following is defined by default in the IDP web.xml, but it is included here for completeness since it is required for CAS integration.
<!-- Servlet protected by container user for RemoteUser authentication --> <servlet> <servlet-name>RemoteUserAuthHandler</servlet-name> <servlet-class>edu.internet2.middleware.shibboleth.idp.authn.provider.RemoteUserAuthServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RemoteUserAuthHandler</servlet-name> <url-pattern>/Authn/RemoteUser</url-pattern> </servlet-mapping>
Test
Restart the IDP servlet and/or servlet container and verify that CAS authentication is used. The TestShib Service Provider is one convenient test option.
Shibbolize CAS
The CASShib project attempts to ease the deployment burden to Shibbolize services that have an existing investment in CAS.
CAS-Shib Integration Facilitates InCommon Assurance
We recently participated in some InCommon Assurance testing with the CILogon service and our integration scenario is both interesting and novel. In particular we were able to quickly develop an integration strategy to assert InCommon Silver for strong authentication at CAS. The high-level integration strategy follows and assumes that CAS is the authentication provider for Shib via the remote authentication mechanism discussed above:
- Compute a synthetic eduPersonAssurance attribute at CAS when the high-security (X509Credentials) credential is successfully authenticated.
- Release eduPersonAssurance to Shib via SAML11-based attribute release capability of CAS.
- Use a custom servlet filter to set the
authnMethod
request attribute accordingly.
It's important to note that the authnMethod
request attribute is handled properly by the Shibboleth IdP to create the protocol-specific identifiers based on the protocols in use by the IdP-SP conversation:
- AuthenticationMethod for SAML1
- AuthenticationContext for SAML2
<saml2:AuthnStatement AuthnInstant="2011-09-22T19:28:28.216Z" SessionIndex="17ba42593e110357eb7b40cf548bd4556b238c8115fa2c8f08f65c945f9cf12f"> <saml2:SubjectLocality Address="10.0.0.1"/> <saml2:AuthnContext> <saml2:AuthnContextClassRef> http://id.incommon.org/assurance/silver </saml2:AuthnContextClassRef> </saml2:AuthnContext> </saml2:AuthnStatement>
Implementation Highlights
We leveraged some existing plumbing to generate the synthetic eduPersonAssurance attribute at CAS. We already calculate an LOA attribute based on the credential type authenticated at CAS. We accept both username/password authentication https://auth.vt.edu and X.509 authentication via certificates that live exclusively on an Aladdin eToken https://auth.vt.edu?pdc=1. It is planned that special classes of eToken credentials will be compliant with InCommon Silver, and we would leverage a similar calculation to LOA to populate the eduPersonAssurance attribute with the Silver URI, http://id.incommon.org/assurance/silver
. Adapting the existing LOA components to support eduPersonAssurance was straightforward if not easy.
The core integration between CAS and Shib happens with a custom servlet filter, AssertionAttributeAuthenticationMethodFilter, that performs a single function: extract the eduPersonAssurance attribute from the CAS assertion and set the authnMethod
request attribute for downstream IdP components.
<filter> <filter-name>CAS Validation Filter</filter-name> <filter-class> org.jasig.cas.client.validation.Saml11TicketValidationFilter </filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>${cas.server.url}</param-value> </init-param> <init-param> <param-name>redirectAfterValidation</param-name> <param-value>false</param-value> </init-param> <init-param> <!-- Adjust to accommodate clock drift between client/server. Increasing tolerance has security consequences, so it is preferable to correct the source of clock drift instead. --> <param-name>tolerance</param-name> <param-value>5000</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/Authn/RemoteUser</url-pattern> </filter-mapping> <filter> <filter-name>AssertionAttributeAuthenticationMethodFilter</filter-name> <filter-class> edu.vt.middleware.shib.cas.AssertionAttributeAuthenticationMethodFilter </filter-class> <init-param> <param-name>authMethodAttribute</param-name> <param-value>eduPersonAssurance</param-value> </init-param> </filter> <filter-mapping> <filter-name>AssertionAttributeAuthenticationMethodFilter</filter-name> <url-pattern>/Authn/RemoteUser</url-pattern> </filter-mapping>
Note the use of the SAML protocol for CAS ticket validation, which is required for release of the eduPersonAssurance attribute to Shib. The filter is fairly flexible, allowing the use of a either an authentication or principal attribute. We chose eduPersonAssurance since it seemed most appropriate for this use case.
The Shibboleth authentication handler configuration needed to be changed to send users to CAS if InCommon silver or bronze are requested by the SP.
<LoginHandler xsi:type="RemoteUser"> <AuthenticationMethod> urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified </AuthenticationMethod> <AuthenticationMethod> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </AuthenticationMethod> <AuthenticationMethod> http://id.incommon.org/assurance/bronze </AuthenticationMethod> <AuthenticationMethod> http://id.incommon.org/assurance/silver </AuthenticationMethod> </LoginHandler>
Shibboleth IDP External Authentication via CAS plugin
This is a Shibboleth IDP external authentication plugin that delegates the authentication to the Central Authentication Server. The biggest advantage of using this component over the plain REMOTE_USER
header solution provided by Shibboleth is the ability to utilize a full range of native CAS protocol features such as renew
and gateway.