CAS Client for Java 3.0

Warning

Users looking for a CAS Client for Java should be using the CAS Client for Java 3.1

Configure the CAS Client for Standalone Applications

Add the Dependencies

To configure the JA-SIG CAS Client for Java, the first thing you need to do is gather the dependencies. If your project is using Maven2, you can include the client by adding the following to your pom.xml:

<dependency>
     <groupId>org.jasig.cas</groupId>
     <artifactId>cas-client-core</artifactId>
     <version>3.0</version>
</dependency>

If you are not using Maven2, you should download the CAS distribution and manually copy in the required dependencies.

Configure the web.xml

You need to add the following XML filter and Spring configuration code to the web.xml

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>

            /WEB-INF/simpleFilter.xml
        </param-value>
    </context-param>

    <filter>
        <filter-name>CAS Authentication Filter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>

            <param-value>casAuthenticationFilter</param-value>
        </init-param>
    </filter>

    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>

            <param-name>targetBeanName</param-name>
            <param-value>casValidationFilter</param-value>
        </init-param>
    </filter>

    <filter>
        <filter-name>CAS Authorization Filter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>casAuthorizationFilter</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CAS Authentication Filter</filter-name>

        <url-pattern>/*</url-pattern>
    </filter-mapping>

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

    <filter-mapping>
        <filter-name>CAS Authorization Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--
      - Loads the root application context of this web app at startup.
      - The application context is then available via
      - WebApplicationContextUtils.getWebApplicationContext(servletContext).
    -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

If you need Proxy support, add the following to your web.xml

<servlet>
	<servlet-name>casclient</servlet-name>
	<servlet-class>org.jasig.cas.client.proxy.SpringConfiguredProxyReceptorServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>casclient</servlet-name>
	<url-pattern>/proxy/Receptor</url-pattern>
</servlet-mapping>

Configure the Spring Bean Factory

Include the following simpleFilter.xml file:

<?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.xsd">

    <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/cas-client.properties"/>
    </bean>

    <bean id="authorizedDecider" class="org.jasig.cas.client.authorization.DefaultAuthorizedDeciderImpl">
        <constructor-arg index="0">
            <list>
                <value>scott</value>
                <value>velpi</value>
                <value>apetro</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="httpClient" class="org.jasig.cas.util.HttpClient3FactoryBean"/>

    <bean id="proxyRetriever" class="org.jasig.cas.client.proxy.Cas20ProxyRetriever">
        <constructor-arg index="0" value="${cas.server.url}"/>
        <constructor-arg index="1" ref="httpClient"/>
    </bean>

    <bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>

    <bean id="ticketValidator" class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
        <constructor-arg index="0" value="${cas.server.url}"/>
        <constructor-arg index="1" value="${cas.server.renew}"/>
        <constructor-arg index="2" ref="httpClient"/>
        <constructor-arg index="3"><list></list></constructor-arg>
        <constructor-arg index="4" value="true"/>
    </bean>

    <bean id="casHttpServletRequestWrapperFilter" class="org.jasig.cas.client.web.filter.HttpServletRequestWrapperFilter"/>

    <bean id="casValidationFilter" class="org.jasig.cas.client.web.filter.TicketValidationFilter">
        <constructor-arg index="0" value="${cas.client.serverName}"/>
        <constructor-arg index="1"><null/></constructor-arg>
        <constructor-arg index="2" ref="ticketValidator"/>
    </bean>

    <bean id="casAuthenticationFilter" class="org.jasig.cas.client.web.filter.AuthenticationFilter">
        <constructor-arg index="0" value="${cas.client.serverName}"/>
        <constructor-arg index="1"><null/></constructor-arg>
        <constructor-arg index="2" value="${cas.server.url}login"/>
        <constructor-arg index="3" value="${cas.server.renew}"/>
        <constructor-arg index="4" value="${cas.server.gateway}"/>
    </bean>

    <bean id="casAuthorizationFilter" class="org.jasig.cas.client.web.filter.AuthorizationFilter">
        <constructor-arg index="0" ref="authorizedDecider" />
    </bean>
</beans>

Configure Your application specific properties.

You'll need to create a file called cas-client.properties:

cas.server.gateway=false
cas.server.renew=false
cas.server.url=https://localhost:8443/cas/
cas.client.serverName=localhost:8443
cas.client.proxyCallbackUrl=https://localhost:8443/myClientApp/casProxyReceptor

uPortal Integration Support

The JA-SIG CAS Client for Java provides out the box support for the uPortal 2.x framework.

Gotchas and alternatives

uPortal in recent releases (later 2.5.x releases and all 2.6 releases) provides out of the box CAS integration support, including example configuration, all necessary libraries, and integration APIs, by means of the Yale Java CAS Client. You do not need to use the JA-SIG Java CAS Client or to follow these instructions to achieve basic CAS integration in uPortal. See instead the uPortal Manual page on this topic, which exists with the purpose of making this as simple and as un-frustrating as possible for you, the uPortal deployer. (It's even named "for the impatient"!)

What is documented here is an alternative to the default approach. However, this alternative will only work with version 3.0.x of the JA-SIG Java CAS Client. It will not work with version 3.1 of the JA-SIG Java CAS Client, in which this uPortal-specific integration code was removed for various reasons. (It's not clear that uPortal-specific code belongs here, and this integration code did not make use of the CAS integration APIs shipping in uPortal, instead introducing new APIs, and so it did not transparently integrate with e.g. the CasConnecionContext shipping with uPortal 2.6).

In short, you're entirely welcome to this this JA-SIG Java CAS Client version 3.0.x and these instructions to accomplish your uPortal-CAS integration, but if you do, you're doing something different than the CAS integration that most uPortal-CAS-integrators are doing.

Add the Dependencies

To configure the JA-SIG CAS Client for Java, the first thing you need to do is gather the dependencies. If your project is using Maven2, you can include the client by adding the following to your pom.xml:

<dependency>
     <groupId>org.jasig.cas</groupId>
     <artifactId>cas-client-uportal</artifactId>
     <version>3.0</version>
</dependency>

If you are not using Maven2, you should download the CAS distribution and manually copy in the required dependencies.

Edit the uPortal security.properties

First, you'll need to edit the security.properties file and set your "root" security context:

root=org.jasig.cas.client.integration.uportal.CasSecurityContextFactory

Next, set the credentials token for the root context:

credentialToken.root=ticket

Add the uPortal-specific configuration

Add the following file to your uPortal configuration files:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/properties/cas-client.properties"/>
    </bean>

    <bean id="casTicketValidator" class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
        <constructor-arg index="0" value="${cas.server.url}"/>
        <constructor-arg index="1" value="false"/>
        <constructor-arg index="2" ref="httpClient"/>
        <constructor-arg index="3">
            <bean class="org.jasig.cas.authentication.principal.SimpleService">
                <constructor-arg value="${cas.server.proxyCallbackUrl}"/>
            </bean>
        </constructor-arg>
        <constructor-arg index="4" ref="casProxyGrantingTicketStorage"/>
        <constructor-arg index="5" ref="casProxyRetriever" />
    </bean>

    <bean id="casProxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>

    <bean id="casProxyRetriever" class="org.jasig.cas.client.proxy.Cas20ProxyRetriever">
        <constructor-arg value="${cas.server.url}"/>
        <constructor-arg ref="httpClient"/>
    </bean>

    <bean id="httpClient" class="org.jasig.cas.util.HttpClient3FactoryBean">
        <property name="soTimeout" value="5000"/>
        <property name="connectionTimeout" value="5000"/>
        <property name="connectionManagerTimeout" value="5000"/>
        <property name="defaultMaxConnectionsPerHost" value="10"/>
        <property name="maxTotalConnections" value="10"/>
    </bean>

    <bean id="casService" class="org.jasig.cas.authentication.principal.SimpleService">
        <constructor-arg value="https://localhost:8443/portal/Authentication"/>
    </bean>
</beans>

Configure the cas-client.properties file

You'll also need a cas-client.properties file:

cas.server.gateway=false
cas.server.renew=false
cas.server.url=https://localhost:8443/cas/
cas.client.serverName=localhost:8443
cas.client.proxyCallbackUrl=https://localhost:8443/myClientApp/casProxyReceptor

Configure the uPortal Spring Bean Factory

You'll need to add the CAS Spring Bean Factory to the uPortal Spring Bean Factory so it can find it. Modify the properties/beanRefFactory.xml to include the file you created above containing the Spring Beans that the CAS client needs.

Accessing the URL:

You should now be able to go to https://my.cas.server/cas/login?service=https://my.uportal.server/portal/Authentication and authenticate via CAS.

Removing service tickets from URLs after validation:

After users have logged into CAS and access a protected service/resource, they are redirected back to the requested service/resource with a CAS service ticket.  The CAS client uses this ticket to determine whether the user has been authenticated by CAS and request the user's username.  However, the service ticket is still on the query string for the request service.  This is a problem whenever the user attempts to refresh the page or return to the page after a later time because the ticket is no longer valid!

 In order for this service ticket to be removed from the URL of the requested service/resource, an alternative configuration of the TicketValidationFilter bean must be used.

<bean id="casValidationFilter" class="org.jasig.cas.client.web.filter.TicketValidationFilter">
	<!-- serverName of client to construct serviceURL eg:"thisServer.myDomain.net" -->
        <constructor-arg index="0" value="${cas.client.serverName}"/>
        <!-- serviceUrl of client: either provide serverName or serviceUrl -->
        <constructor-arg index="1">
            <null/>
        </constructor-arg>
        <!-- use sessions -->
        <constructor-arg index="2" value="true"/>
        <!-- ticketValidator implementation (defines protocol version to be used) -->
        <constructor-arg index="3" ref="ticketValidator"/>
        <!-- redirect users to the service after validation to remove service ticket -->
        <constructor-arg index="4" value="true"/>
</bean>