End-to-end Windows Example

This tutorial demonstrates Active Directory authentication, MySQL-based registries, LDAP attribute release and single sign-off using the 3.4.2.1 server and 3.1.10 client running on Windows XP systems. The Maven overlay method is used to build the server.

Overview

This document describes work I did to evaluate CAS. This is intended to be a beginner's introduction. I'm not a member of the CAS team and I don't have a lot of experience with the system, so I imagine there are more efficient ways to go about this - feel free to correct errors or improve the results!

I think the following is a fairly realistic implementation of a CAS SSO environment. I say "fairly" because it doesn't reflect some things that a real production deployment would have, i.e., a high-availability architecture.

The system demonstrates the following features in one of many possible CAS setups:

  • Database-resident ticket and service registries using JPA/Hibernate/MySQL
  • Name/password authentication using Active Directory
  • LDAP user attributes released to the client
  • Single sign-off

And it shows how I used the Maven overlay method to build the server.

The CAS system requires a ticket registry to hold the artifacts of the users' login sessions. A service registry is required to hold information on which applications are allowed to use the SSO infrastructure, as well as which user attributes can be released to each application. Both the ticket registry and the service registry are kept in a MySQL database running on the CAS server.

There are two test applications running on a protected web server. Single sign-on can be exercised by following links between the two apps. The test application is described later.

Prerequisites

Install the Required Software

Java JDK

This demo uses JDK version 1.6_20. Make sure the JAVA_HOME system environment variable points to the JDK, e.g., C:\Program Files\Java\jdk1.6.0_20. Make sure the java executables directory is in the PATH environment variable, i.e., %JAVA_HOME%\bin.

Maven

Maven is a project management application that uses xml files to specify a project's dependencies and the repositories they reside in. Dependencies are downloaded to the local system as part of the build process.

Get maven from this download site. This demo uses version 2.2.1.

Make sure the M2_HOME environment variable points to the installation folder, and that the maven executables directory is in the PATH, i.e., %M2_HOME%\bin.

The maven overlay method is the preferred way to build the CAS server and to maintain local configuration changes. Setting up the registries and the LDAP interface involves a couple configuration files, and maven helps to create a deployable war that includes the modified config files. You only need to install this on the machine where you'll maintain your CAS build.

Tomcat

Get tomcat from this download site. This demo uses version 6.0.29, and expects that you've extracted the zip file to C:\. Install tomcat on both the SSO server and the test applications server.

Once installed, edit C:\apache-tomcat-6.0.29\conf\tomcat-users.xml to add a privileged user so you can access the tomcat console.

<user username="admin" password="password" roles="manager"/>

Start tomcat and make sure no errors occur in the console. Launch a browser and navigate to http://localhost:8080 and verify that the tomcat page comes up. Access the Tomcat Manager and verify that you can login as the 'admin' user declared above. If you can do all this, your basic tomcat installation is good.

CAS can run on JBoss, but its baseline is tomcat. Tomcat starts faster and is easier to administer, so I stuck with tomcat for this demo.

MySQL

Get MySQL from this download site and install it. This demo uses version 5.1.50, and I have MySQL Administrator 1.2.17. Install this on the SSO server.

Portecle

Portecle is a X.509 certificate and keystore management tool, and it's a lot easier to use than the Java keytool. Get Portecle from this download site and install it everywhere. This demo uses version 1.5.

Extract the zip file to C:\, and once installed you can launch the application by double-clicking C:\Portecle\portecle.jar.

Create the X.509 Certificates

CAS uses SSL connections between the SSO server and the protected servers when performing ticket validation, passing user attributes, etc. In fact, it's recommended that SSL be used for all client and server connections since the user's authentication travels in a cookie.

This means the SSO server and all protected servers must each have a server certificate. These certificates are used to establish trust between the various clients and servers.

  • The CAS SSO server must trust the servers its protecting, so their server certs must be installed in the SSO server's trust store, i.e., the JDK's cacerts keystore. Without this the SSO server won't accept validation requests, etc., from the other servers.
  • The protected application servers must trust the CAS SSO server, so that server's cert must be installed in each protected server's trust store, i.e., their JDK's cacerts keystore. Without this the SSO client won't accept single sign-out messages, etc., from the CAS server.
  • All of these servers must be configured to send their server cert as part of accepting SSL connection requests. Tomcat's server.xml file does this as described below.

This demo uses self-signed certs for convenience. In production you'll want to get server certificates issued by your local Certification Authority or by a commercial CA.

Use Portecle to create a keystore and a server certificate for the CAS SSO server. Name the keystore ssoServer.jks. Set the certificate's alias to 'tomcat', and its common name (CN) to the server's fully-qualifed domain name (FQDN), e.g., ssoserver.merlin.com. Make the password for the certificate the same as the password for the keystore.

Export the server certificate to a file, e.g., ssoServer.cer, so that it can be imported into the protected server's cacerts keystore later.

Repeat the process for the server running the test applications. Name the keystore ssoClient.jks. Set the certificate's alias to 'tomcat' and its CN to the server's FQDN, e.g., ssoclient.merlin.com. Export the certificate.

On the SSO server, import the test app server's certificate into the cacerts trust store, which is located here:

C:\Program Files\Java\jdk1.6.0_20\jre\lib\security\cacerts

The default cacerts password is 'changeit'

On the test apps server, import the SSO server's certificate into the cacerts trust store.

Configure Tomcat to Accept SSL Connections

On both server machines, edit C:\apache-tomcat-6.0.29\conf\server.xml. Uncomment the port 8443 connector and add information for the local machine's server certificate keystore, created above, including file path, password and cert alias. This is what allows the server to send its certificate to clients as part of accepting an SSL connection.

The connector element below, for the SSO server, shows that I copied my keystore into C:\apache-tomcat-6.0.29\conf. Make sure the password and alias match what was used to create the keystore and cert.

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
   SSLEnabled="true" maxThreads="150" scheme="https" secure="true"
   keystoreFile="conf/ssoServer.jks" keyAlias="tomcat" keystorePass="changeit"
   clientAuth="false" sslProtocol="TLS"
/>

Set the connector protocol to org.apache.coyote.http11.Http11Protocol

Test

Start tomcat and make sure no errors occur in the console. If errors occur it may be that your keystore can't be found.

Browse to the tomcat admin console, using the SSL URL containing the host's FQDN, e.g., https://ssoserver.merlin.com:8443/. If you have trouble, verify that you imported the trusted cert into the right cacerts file.

Prepare the Registry Database

On the SSO server machine, run MySQL Administrator (if you have it). Create a new schema: cas_sso. Most of the required database tables will be created by CAS during the initial system startup... except for the locks table, which is used by the registry cleaner.

Create the ticket registry locks table with the following columns:

CREATE TABLE LOCKS (
  APPLICATION_ID VARCHAR(50) NOT NULL,
  UNIQUE_ID VARCHAR(50) NULL,
  EXPIRATION_DATE TIMESTAMP NULL
);
ALTER TABLE LOCKS ADD CONSTRAINT LOCKS_PK
PRIMARY KEY (APPLICATION_ID);

If you have MySQL Administrator it looks like this:

Use the Maven Overlay Method to Build the SSO Server

The Starter Pom

On your server build system, create a folder to hold your local project, e.g., this demo uses C:\CAS_SSO\local-cas. Create a file, pom.xml, in that directory and copy in this xml:

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.merlin</groupId>
  <artifactId>local-cas</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
          <configuration>
             <warName>cas</warName>
          </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.jasig.cas</groupId>
      <artifactId>cas-server-webapp</artifactId>
      <version>${cas.version}</version>
      <type>war</type>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.jasig.cas</groupId>
      <artifactId>cas-server-support-ldap</artifactId>
      <version>${cas.version}</version>
    </dependency>
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.13</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.5.0-CR-2</version>
      <scope>runtime</scope>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>concurrent</groupId>
      <artifactId>concurrent</artifactId>
      <version>1.3.4</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
  <properties>
    <cas.version>3.4.2.1</cas.version>
  </properties>
  <repositories>
    <repository>
      <id>ja-sig</id>
      <url>http://oss.sonatype.org/content/repositories/releases/</url>
    </repository>
    <repository>
      <id>jboss</id>
      <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
    </repository>
  </repositories>
</project>

Change the top level groupId, artifactId and version to whatever you need for your organization.

A few things to point out:

  • the cas.version property is set to 3.4.2.1 for this demo
  • the dependency, cas-server-webapp, is the core server application
  • the dependency on cas-server-support-ldap adds LDAP capabilities to our server
  • the dependency on mysql-connector-java adds the MySQL database driver
  • the remaining dependencies are related to the JPA/Hibernate database access framework
  • I added the JBoss repository because I kept having failed-to-find-resource errors

The Initial Server Build

This build just downloads the initial set of components, including the configuration files we'll use to create the server system. Open a console window and navigate to C:\CAS_SSO\local-cas and execute the maven command to build the project:

mvn clean package -DskipTests=true

This will download almost a thousand files into your local repository, which by default is in C:\Documents and Settings\Your.Name\.m2\repository.

When the build completes you will find a new directory in your build folder: target. The target directory contains the build results, including the cas.war archive.

Test

You can test the initial build by deploying this "out-of-the-box" CAS server. Copy the cas.war to C:\apache-tomcat-6.0.29\webapps. Start tomcat, browse to the Tomcat Manager admin console and verify that CAS is running.

Select the /cas application and you should see the CAS login page. Enter identical username and password ("test", "test") and the default authentication mechanism should send you to the CAS login successful page.

Configuring the SSO Server

This demo requires modifications to three of the CAS configuration files. One way to get hold of them is to copy them out of the build target directory and into a src directory where they can be modified and maintained. Another way to get them would be to check them out of the CAS repository, I guess.

Create the src directory, at the same level as target, and its sub-directories as shown below. These folders will receive the needed configuration files.

Navigate into the target directories and copy the configuration files (highlighted in the image) into their corresponding src sub-directories as listed below:

C:\CAS_SSO\local-cas\src\main\webapp\WEB-INF
   cas.properties
   deployerConfigContext.xml

C:\CAS_SSO\local-cas\src\main\webapp\WEB-INF\spring-configuration
   ticketRegistry.xml

The WEB-INF\classes directory holds the log4j.xml file. If you want to modify the log4j settings for your build you can grab that file, too.

Edit cas.properties to set up Services Management

Set up the Services Management URL, and the database platform type of the services registry.

# Point to the server that hosts Services Management
cas.securityContext.serviceProperties.service=http://localhost:8080/cas/services/j_acegi_cas_security_check
cas.securityContext.casProcessingFilterEntryPoint.loginUrl=http://localhost:8080/cas/login
cas.securityContext.ticketValidator.casServerUrlPrefix=http://localhost:8080/cas

# Names of roles allowed to access the CAS service manager
cas.securityContext.serviceProperties.adminRoles=ROLE_ADMIN

# The database platform is "SQL92" since MySQL meets that standard
ticket.cleaner.database.platform=SQL92
database.hibernate.dialect=org.hibernate.dialect.MySQLDialect

host.name=cas
cas.themeResolver.defaultThemeName=default
cas.viewResolver.basename=default_views

Host.name is the public domain issued and should match any https/ssl cert used.

Edit deployerConfigContext.xml

This file holds most of the configuration settings needed for this demo. The file is attached but details follow.

The deployerConfigContext.xml file contains a set of bean definitions along with the properties they need. They include the authenticationManager bean (with properties defining credentials resolvers and authentication handlers), the contextSource bean, attributeRepository, serviceRegistryDao, etc.

Define and configure the LDAP context source

This object provides connections to the LDAP. Add as many URLs as desired to the list. Set the userDn and password to the credentials of a service account created for user lookups.

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
  <property name="anonymousReadOnly" value="false" />
  <property name="userDn" value="CN=lookupAcct,CN=Users,DC=merlin,DC=com" />
  <property name="password" value="secret" />
  <property name="pooled" value="true" />
  <property name="urls">
    <list>
      <value>ldap://ssoserver.merlin.com/</value>
    </list>
  </property>
  <property name="baseEnvironmentProperties">
    <map>
      <entry>
        <key><value>java.naming.security.authentication</value></key>
        <value>simple</value>
      </entry>
    </map>
  </property>
</bean>
Identify the Attribute Repository

We will pass LDAP user attributes to the client. To do so we declare an attribute repository and, since the repository is our LDAP, we tell it to use the context source defined above. Edit the baseDN as needed for your domain.

<bean id="attributeRepository"
  class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao">

  <property name="contextSource" ref="contextSource" />
  <property name="baseDN" value="DC=merlin,DC=com" />
  <property name="requireAllQueryAttributes" value="true" />
  <property name="ldapTemplate" ref="ldapTemplate" />

  <!--
  Attribute mapping between principal (key) and LDAP (value) names
  used to perform the LDAP search.
  -->
  <property name="queryAttributeMapping">
    <map>
      <entry key="username" value="sAMAccountName" />
    </map>
  </property>

  <property name="resultAttributeMapping">
    <map>
      <!-- Mapping between LDAP attributes (key) and Principal's (value) -->
      <entry value="CN" key="cn" />
      <entry value="DN" key="distinguishedName" />
      <entry value="Groups" key="memberOf" />
    </map>
  </property>
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
  <constructor-arg ref="contextSource" />
  <property name="ignorePartialResultException" value="true" />
</bean>

The resultAttributeMapping determines which user attributes may be released to the client. In this example, the CAS Services Management and the client's Principal will both refer to the attributes by the names CN, DN and Groups.

Note that an LdapTemplate bean is used to inject a property that enables correct handling of Active Directory partial results exceptions.

Add an LDAP attribute principal resolver to the authenticationManager bean

The authenticationManager bean has a list of credentialsToPrincipalResolvers. This adds one that will do an LDAP lookup based on the sAMAccountName entered by the user, and will define the Principal available to the client application. This uses the context source and the attribute repository defined above. Edit the searchBase as needed for your directory's structure.

<bean
  class="org.jasig.cas.authentication.principal.CredentialsToLDAPAttributePrincipalResolver">

  <!-- The Principal resolver form the credentials -->
  <property name="credentialsToPrincipalResolver">
    <bean
    class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
  </property>

  <!-- "%u" will be replaced by the resolved Principal -->
  <property name="filter" value="(sAMAccountName=%u)" />

  <!-- The attribute used to define the new Principal ID -->
  <property name="principalAttributeName" value="sAMAccountName" />

  <property name="searchBase" value="DC=merlin,DC=com" />
  <property name="contextSource" ref="contextSource" />

  <property name="attributeRepository">
    <ref bean="attributeRepository" />
  </property>
</bean>
Add an LDAP authentication handler to the authenticationManager bean

The authenticationManager bean has a list of authenticationHandlers. This adds one that, once user lookup has been completed, will authenticate the user by opening a context using the retrieved distinguished name and the entered password. This bean also uses the context source defined above. Edit the searchBase as needed for your directory's structure.

<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler">
  <property name="filter" value="sAMAccountName=%u" />
  <property name="searchBase" value="DC=merlin,DC=com" />
  <property name="contextSource" ref="contextSource" />
  <property name="ignorePartialResultException" value="yes" /> <!-- handle AD partial results -->
</bean>
Configure the service registry

The demo's service registry is in a MySQL database accessed via the Java Persistence Architecture (JPA) and Hibernate. The following beans specify the database type, enable automatic table creation and provide for connections to the database. Some of these beans will be shared by the ticket registry and referenced from the ticketRegistry.xml file. Edit the dataSource username and password properties as needed.  (Edit deployerConfigContext.xml)

You must add the "tx" namespace to the top of the file!

<bean id="serviceRegistryDao"
  class="org.jasig.cas.services.JpaServiceRegistryDaoImpl"
  p:entityManagerFactory-ref="entityManagerFactory" />

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

  <property name="dataSource" ref="dataSource"/>
  <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="generateDdl" value="true"/>
      <property name="showSql" value="true" />
    </bean>
  </property>
  <property name="jpaProperties">
  <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.hbm2ddl.auto">update</prop>
  </props>
  </property>
</bean>

<bean id="transactionManager"
  class="org.springframework.orm.jpa.JpaTransactionManager">

  <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource"
  p:driverClassName="com.mysql.jdbc.Driver"
  p:url="jdbc:mysql://localhost:3306/cas_sso?autoReconnect=true"
  p:password="secret"
  p:username="root" />
Authorize users who will access Services Management

Enter the LDAP sAMAccountNames of users who will be able to run the CAS Services Management. The password is not used so just enter 'notused'.

<sec:user-service id="userDetailsService">
<sec:user name="ndoe" password="notused" authorities="ROLE_ADMIN" />
</sec:user-service>

These can't be service accounts - only normal domain user accounts

Edit ticketRegistry.xml

The beans providing database access for the ticket registry have already been defined
in deployerConfigContext.xml, since the service registry is held in the same database.
So, we only need to declare the ticket registry and add some stuff for the registry
cleaner.

Replace the file's contents with the following or use this attached file.

<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.JpaTicketRegistry">
  <constructor-arg index="0" ref="entityManagerFactory" />
</bean>

<bean id="ticketRegistryCleaner"
  class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
  p:ticketRegistry-ref="ticketRegistry"
  p:lock-ref="cleanerLock"
/>

<bean id="cleanerLock"
  class="org.jasig.cas.ticket.registry.support.JdbcLockingStrategy"
  p:uniqueId="${host.name}"
  p:platform="${ticket.cleaner.database.platform}"
  p:applicationId="cas-ticket-registry-cleaner"
  p:dataSource-ref="dataSource"
/>

<bean id="ticketRegistryCleanerJobDetail"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
  p:targetObject-ref="ticketRegistryCleaner"
  p:targetMethod="clean"
/>

<bean id="periodicTicketRegistryCleanerTrigger"
  class="org.springframework.scheduling.quartz.SimpleTriggerBean"
  p:jobDetail-ref="ticketRegistryCleanerJobDetail"
  p:startDelay="20000"
  p:repeatInterval="1800000"
/>

The properties in the cleanerLock bean, host.name and ticket.cleaner.database.platform, are defined in cas.properties.

The Final Server Build

Now that the maven pom file and the CAS configuration files have been modified we're ready to build the deployable CAS war. Once again, open a console window and navigate to C:\CAS_SSO\local-cas and execute the maven command to build the project:

mvn clean package -DskipTests=true

Deploy the Server

Stop tomcat if it's running, and copy the cas.war file into C:\apache-tomcat-6.0.29\webapps. Start tomcat and verify that no exceptions appear in the console.

Test

Browse to the Tomcat Manager admin console and verify that CAS is running. Browse to the Tomcat Manager, select the /cas application and you should see the CAS login page. This time, since the "real" CAS server is running, you should be able to login using your LDAP credentials.

Enter your sAMAccountName and password and you should see the CAS login successful page.

Optional: Verify the database tables have been created

CAS will have created the rest of the database tables that it needs for the registries, or the preceding test would've failed. Still, if you feel interested you can run MySQL Administrator, go to the cas_sso schema and verify that the five service and ticket registry tables are present.

  • locks
  • registeredServiceImpl
  • rs_attributes
  • serviceTicket
  • ticketGrantingTicket

Enable the Client Services in Services Management

Browse to http://localhost:8080/cas/services/manage.html, the Services Management application. Once you login you'll see a warning to add the Management service itself as the first service. Click the 'Add New Service' button and add a service with the following URL:

http://localhost:8080/cas/services/j_acegi_cas_security_check

If you mess up entering the service and end up unable to access Services Management, you can reset by dropping the CAS tables in the database - but don't drop the LOCKS table or you'll have to recreate it (just remove any records it may have).

Add a couple services for the test applications, Test App 1 and Test App 2. In the image below you can see I've added TestApp1 using the https URL with a wildcard that will match any page in the protected area, /sso/*. For each service, select the attributes you wish to release to the client.

Deploy the Protected Applications

This zip file contains two web applications, TestApp1 and TestApp2. Each application has an un-protected page that anyone can access and a protected servlet that users must login to access.

Download and extract the archive to C:\ on your protected server machine; it'll create C:\CasTestApp and subdirectories.

Go to the C:\CasTestApp\src directory and edit the two web.xml files there.

  • Replace all occurrences of [CAS Server FQDN] with your CAS server's fully-qualified domain name.
  • Replace all occurrences of [Client Server FQDN] with your test application server's fully-qualified domain name.

Go to C:\CasTestApp and execute the Deploy.bat script and it'll put together the TestApp1 and TestApp2 war files and copy them to C:\apache-tomcat-6.0.29\webapps.

All you need to do is start tomcat on the protected server and you should be ready to test.

The Test Applications

Access the test application entry points using these URLs:

https://<protected.server.com>:8443/TestApp1/index.jsp
https://<protected.server.com>:8443/TestApp2/index.jsp

The pages in the applications include links to the protected and unprotected pages of the other application. You can exercise the single sign-on function by navigating between the apps, e.g., between tabs in the same browser, between browser instances, etc.

Accessing a protected page for the first time will require user login. Once accessed, the page displays interesting information as shown below.

The protected pages have buttons for both application logout and single sign-out. Application logout invalidates the current session. Note that if you still have a valid CAS SSO login session, i.e., you're in another protected application in a different browser tab, then navigating to the protected page again will log you right back in.

Single sign-out, on the other hand, will require you to login again for any action that accesses a protected page, even refreshing the page.

CAS-ifying the Client Applications

Get the CAS Java Client

You can get the official CAS 3.1.10 client for Java from http://downloads.jasig.org/cas-clients/. Download the cas-client-3.1.10-release.zip file, which extracts to cas-client-3.1.10 and includes a modules subdirectory.

The contents of the modules directory includes jars for the CAS client classes and their dependencies. I copied all of those into the test application's WEB-INF\lib directory.

Add the CAS Filters to the Protected Applications

The web.xml file for the test applications have been modified to include the CAS filters. The order of the filters and their URL patterns (in the filter mapping elements) is important.

The URL patterns determine which pages are protected by CAS. The patterns should match what was entered into Services Management. Note that the URL pattern for the single sign-out filter matches all pages in the app.

<filter>
  <filter-name>CAS Single Sign Out Filter</filter-name>
  <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<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>https://[CAS Server FQDN]:8443/cas/login</param-value>
  </init-param>
  <init-param>
    <param-name>serverName</param-name>
    <param-value>https://[Client Server FQDN]:8443</param-value>
  </init-param>
</filter>
<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>https://[CAS Server FQDN]:8443/cas</param-value>
  </init-param>
  <init-param>
    <param-name>serverName</param-name>
    <param-value>https://[Client Server FQDN]:8443</param-value>
  </init-param>
  <init-param>
    <param-name>redirectAfterValidation</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>tolerance</param-name>
    <param-value>5000</param-value>
  </init-param>
</filter>
<filter>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter>
  <filter-name>CAS Assertion Thread Local Filter</filter-name>
  <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>CAS Single Sign Out Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>CAS Authentication Filter</filter-name>
  <url-pattern>/sso/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/sso/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <url-pattern>/sso/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>CAS Assertion Thread Local Filter</filter-name>
  <url-pattern>/sso/*</url-pattern>
</filter-mapping>

...the rest of the application...

Accessing the User Attributes

The user's LDAP attributes are added to the Principal. They can be accessed in a servlet or JSP as shown below.

// get the user's credentials
Principal p = request.getUserPrincipal();
String userLoginName = request.getRemoteUser(); // or p.getName()

// get the released attributes, e.g., LDAP group membership - earlier mapped to 'Groups'
AttributePrincipal principal = (AttributePrincipal)p;
Map attributes = principal.getAttributes();
Object value = attributes.get("Groups");
if (value instanceof String) {
   // memberOf contained one group name
} else if (value instanceof List) {
   // memberOf contained multiple group names
}

Implementing Single Sign-out

The single sign-out button invokes the LogoutServlet, which contains the method shown below. It redirects to the CAS logout URL, which causes CAS to issue logout commands to all apps that are participating in the login session.

public void doSingleSignOut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
  response.sendRedirect("https://<cas.server.com>:8443/cas/logout");
}