Skip to content
This repository has been archived by the owner on Oct 24, 2020. It is now read-only.

Authentication plugin for Shibboleth delegating to CAS for user login and supporting CAS features.

Notifications You must be signed in to change notification settings

Unicon/shib-cas-authenticator

Repository files navigation

NOTICE

This repository and source code is not maintained anymore!!! Instead the v2 of this sofware has been developed and is maintained in the separate repository here Also, if you are running this version of the authenticator, consider upgrading to v2 as it has a more solid and robust architecture as well as simplified configuration model.

Security Patch

Version 1.3.0.1 of shib-cas-authenticator is a security fix for a critical security vulnerability.

See SECURITY-PATCH.md for information and the patch directory for ready-to-install precompiled binary files.

You must patch immediately. This is a serious security vulnerability. No version of shib-cas-authenticator prior to 1.3.0.1 should be used.

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.

The plugin consists of 2 components:

  • A web resource protected by CAS and acting as an authentication facade
  • Shibboleth IDP Servlets acting as a bridge between CAS and IDP

Strategy for sharing state between CASified resource and IdP

The CASified resource uses the Java CAS Client to participate in the CAS protocol to determine the authenticated username. It then publishes this username into the IdP's ServletContext using a cross-context access to put an attribute into that ServletContext keyed by the end user session identifier (with a namespacing prefix). The IdP and the CASified resource have the same session identifier for the user session thanks to the configuration described below.

Software Requirements

  • This plugin will require Shibboleth Identity Provider v2.4.0 and above.

  • The Shibboleth IdP and the web resource protected by CAS (/casauth) must be deployed alongside one another in the same servlet container

  • The servlet container must be configured such that casauth is able to do a cross-context request to access the IdP's ServletContext. Detailed following.

  • The servlet container must be configured such that /casauth and the IDP (/idp) share session identifiers. This is the emptySessionPath="true" tomcat feature. Detailed following.

Servlet Container Configuration

Here's how you do the cross-context enablement in Tomcat 6:

  • Enable Tomcat's crosscontext in $CATALINA_HOME/conf/context.xml
<Context crossContext="true">
	...
</Context>

Here's how you do the empty session path in Tomcat 6:

  • Enable Tomcat's SSL Connector's emptySessionPath in $CATALINA_HOME/conf/server.xml
 <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" emptySessionPath="true" .../>

For Tomcat 7, see SECURITY-PATCH.md

Configure build and deploy cas-authentication-facade resource

  • Configure a context-param to tell the facade the path to the IdP

In cas-authentication-facade/src/main/webapp/WEB-INF/web.xml :

<context-param>
   <param-name>idPContextName</param-name>
   <param-value>/idp</param-value>
</context-param>

If you've deployed your IdP as /samlThing, then the param-value should be

<param-value>/samlThing</param-value>

Defaults to /idp. If your IDP is at /idp, you can omit this context-param.

  • Configure CAS filters in cas-authentication-facade/src/main/webapp/WEB-INF/web.xml suitable for your CAS installation.

Example web.xml:

...
<filter>
	<filter-name>CAS Authentication Filter (Renew)</filter-name>
	<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
	<init-param>
		<param-name>casServerLoginUrl</param-name>
		<param-value>https://sso.server.edu/cas/login</param-value>
	</init-param>
	<!--
		The value of the serverName parameter should be the FQDN of the application server (tomcat)
		where the casauth.war application is deployed.
		
		This configuration assumes that the WAR file is lives inside the same application instance
		in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
		the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
		
		Note: Use the standard IdP operating port and not the SOAP endpoint.
	-->
	<init-param>
		<param-name>serverName</param-name>
		<param-value>https://sso.server.edu</param-value>
	</init-param>
	<init-param>
		<param-name>renew</param-name>
		<param-value>true</param-value>
	</init-param>
</filter>
   
<filter-mapping>
	<filter-name>CAS Authentication Filter (Renew)</filter-name>
	<url-pattern>/facade/renew/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>CAS Authentication Filter (No Renew)</filter-name>
    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
    <init-param>
        <param-name>casServerLoginUrl</param-name>
        <param-value>https://sso.server.edu/cas/login</param-value>
    </init-param>
    <!--
      The value of the serverName parameter should be the FQDN of the application server (tomcat)
      where the casauth.war application is deployed.
      
      This configuration assumes that the WAR file is lives inside the same application instance
      in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
      the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
      
      Note: Use the standard IdP operating port and not the SOAP endpoint.
    -->
    <init-param>
      <param-name>serverName</param-name>
      <param-value>https://sso.server.edu</param-value>
    </init-param>
    <init-param>
        <param-name>renew</param-name>
        <param-value>false</param-value>
    </init-param>
</filter>
    
<filter-mapping>
    <filter-name>CAS Authentication Filter (No Renew)</filter-name>
    <url-pattern>/facade/norenew/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>CAS Authentication Filter (Renew Gateway)</filter-name>
    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
    <init-param>
      <param-name>casServerLoginUrl</param-name>
      <param-value>https://sso.server.edu/cas/login</param-value>
    </init-param>
		<!--
			The value of the serverName parameter should be the FQDN of the application server (tomcat)
			where the casauth.war application is deployed.
			
			This configuration assumes that the WAR file is lives inside the same application instance
			in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
			the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
			
			Note: Use the standard IdP operating port and not the SOAP endpoint.
		-->
		<init-param>
			<param-name>serverName</param-name>
			<param-value>https://sso.server.edu</param-value>
		</init-param>
    <init-param>
        <param-name>renew</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>gateway</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
    
<filter-mapping>
    <filter-name>CAS Authentication Filter (Renew Gateway)</filter-name>
    <url-pattern>/facade/renewgateway/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>CAS Authentication Filter (No Renew Gateway)</filter-name>
    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
    <init-param>
        <param-name>casServerLoginUrl</param-name>
        <param-value>https://sso.server.edu/cas/login</param-value>
    </init-param>
    <!--
      The value of the serverName parameter should be the FQDN of the application server (tomcat)
      where the casauth.war application is deployed.
      
      This configuration assumes that the WAR file is lives inside the same application instance
      in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
      the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
      
      Note: Use the standard IdP operating port and not the SOAP endpoint.
    -->
    <init-param>
      <param-name>serverName</param-name>
      <param-value>https://sso.server.edu</param-value>
    </init-param>
    <init-param>
        <param-name>renew</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>gateway</param-name>
        <param-value>true</param-value>
    </init-param>
 </filter>
 
<filter-mapping>
    <filter-name>CAS Authentication Filter (No Renew Gateway)</filter-name>
    <url-pattern>/facade/norenewgateway/*</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>https://sso.server.edu/cas</param-value>
	</init-param>
	<!--
		The value of the serverName parameter should be the FQDN of the application server (tomcat)
		where the casauth.war application is deployed.
		
		This configuration assumes that the WAR file is lives inside the same application instance
		in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
		the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
		
		Note: Use the standard IdP operating port and not the SOAP endpoint.
	-->
	<init-param>
		<param-name>serverName</param-name>
		<param-value>https://sso.server.edu</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>/facade/renew/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/facade/norenew/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/facade/renewgateway/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/facade/norenewgateway/*</url-pattern>
</filter-mapping>
...

Configure build and deploy IdP external authentication plugin

  • Make sure that IDP is deployed and war is exploded as $CATALINA_HOME/webapps/idp
  • Configure IDP External Login Handler in $IDP_HOME/conf/handler.xml

Example:

...

<ph:LoginHandler xsi:type="ph:ExternalAuthn"
                 externalAuthnPath="/authn/external"
                 supportsForcedAuthentication="true" >
    <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</ph:AuthenticationMethod>
</ph:LoginHandler>

...
  • Add the IDP External Auth Servlet entries in $CATALINA_HOME/webapps/idp/WEB-INF/web.xml

Example:

	<!-- Servlet for invoking external CAS authentication -->
	   <servlet>
	       <servlet-name>External Authn</servlet-name>
	       <servlet-class>net.unicon.idp.externalauth.CasInvokerServlet</servlet-class>

	       <!-- 
            A URL for CAS-protected resource endpoint  
            The value of the casProtectedResource parameter should be the FQDN of the application server (tomcat)
            where the casauth.war application is deployed.
            
            This configuration assumes that the WAR file is lives inside the same application instance
            in which CAS itself is deployed. If your configuration has deployed the WAR file alongside
            the IdP server, the value should then be changed to be the FQDN of the IdP tomcat server.
            
            Note: Use the standard IdP operating port and not the SOAP endpoint.
          -->
	       <init-param>
	           <param-name>casProtectedResource</param-name>
	           <param-value>https://sso.server.edu/casauth/facade</param-value>
	       </init-param>
	       <!-- Am IdP URL for the external CAS-protected resource to callback to -->
	       <init-param>
	           <param-name>postAuthnCallbackUrl</param-name>
	           <param-value>https://shibidp.server.edu/idp/externalAuthnCallback</param-value>
	       </init-param>

	       <load-on-startup>2</load-on-startup>
	   </servlet>

	   <servlet-mapping>
	       <servlet-name>External Authn</servlet-name>
	       <url-pattern>/authn/external</url-pattern>
	   </servlet-mapping>

	   <!-- Servlet for receiving a callback from an external authentication system and continuing the IdP login flow -->
	   <servlet>
	       <servlet-name>External Authn Callback</servlet-name>
	       <servlet-class>net.unicon.idp.externalauth.CasCallbackServlet</servlet-class>

	       <load-on-startup>2</load-on-startup>
	   </servlet>

	   <servlet-mapping>
	       <servlet-name>External Authn Callback</servlet-name>
	       <url-pattern>/externalAuthnCallback</url-pattern>
	   </servlet-mapping>

To Build

This project uses Gradle build system.

  • In gradle.properties, adjust the property settings for the IdP path, version and Shibboleth common JAR file dependency version:
shibIdpVersion=2.4.0
shibCommonVersion=1.4.0
shibIdpPath=/opt/shibboleth-idp
  • From the root directory, simply run ./gradlew

  • Copy cas-authentication-facade/build/libs/casauth.war to $CATALINA_HOME/webapps

  • Copy idp-cas-invoker/build/libs/idp-cas-invoker-x.x.jar to $CATALINA_HOME/webapps/idp/WEB-INF/lib

To Build in IntelliJ IDE

The IntelliJ metadata files included declare the Shibboleth IdP .jar dependency as version 2.4.0 obtained from /opt/shibboleth-idp. If you first install the IdP there, then IntelliJ should find the Shibboleth IdP .jar dependency and be able to build in the IDE. If you want to use a different IdP version or a different IdP location, you'll have some IntelliJ library configuration to do.

Shibboleth IdP Upgrades

In order to properly protect the changes to the web.xml file of the Shibboleth IdP between upgrades, copy the changed version to the conf directory of the main Shib IdP directory (e.g. usually /opt/shibboleth-idp/conf). Then, rebuild and redeploy the IdP as usual.

See the following links for additional info: