MemcacheTicketRegistry

New CAS documentation site

CAS documentation has moved over to apereo.github.io/cas, starting with CAS version 4.x. The wiki will no longer be maintained. For the most recent version of the documentation, please refer to the aforementioned link.

MemCacheTicketRegistry

As of CAS 3.3, a MemCacheTicketRegistry is provided.

Add the Memcached Client Artifact to Your WAR Overlay

Add the following to your pom.xml:

<dependency>
	<groupId>org.jasig.cas</groupId>
	<artifactId>cas-server-integration-memcached</artifactId>
	<version>${cas.version}</version>
	<type>jar</type>
</dependency>

Configuration

Version Specific Notice

Note that the configuration of memcached clients was simplified and extended for 3.5.0.

CAS 3.5+ Memcached Configuration
<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.MemCacheTicketRegistry">
  <constructor-arg index="0" ref="memcachedClient" />
  
  <!-- TGT timeout in seconds -->
  <constructor-arg index="1" value="${expiration.policy.tgt.validity_period}" />
 
  <!-- ST timeout in seconds -->
  <constructor-arg index="2" value="${expiration.policy.st.validity_period}" />
</bean>

<!--
  NOTE: Changing the transcoder implementation is not required, but Kryo provides for more
  efficient serialization which significantly improves throughput and storage footprint.
  See http://code.google.com/p/spymemcached/wiki/SpringIntegration for more info on options
  for various property values.
-->
<bean id="memcachedClient" class="net.spy.memcached.spring.MemcachedClientFactoryBean"
      p:servers="${memcached.servers}"
      p:protocol="${memcached.protocol}"
      p:locatorType="${memcached.locatorType}"
      p:failureMode="${memcached.failureMode}"
      p:transcoder-ref="kryoTranscoder">
  <property name="hashAlg">
    <util:constant static-field="net.spy.memcached.DefaultHashAlgorithm.${memcached.hashAlgorithm}" />
  </property>
</bean>
<bean id="kryoTranscoder"
      class="org.jasig.cas.ticket.registry.support.kryo.KryoTranscoder"
      init-method="initialize">
  <!-- initialBufferSize -->
  <constructor-arg index="0" value="8192" />
</bean> 

Using the KryoTranscoder bean offers a better serialization efficiency. By default, the objects used in the cas-server-core module are registered for the Kryo serialization. Other objects must be registered explicitely using the setSerializerMap method. Since CAS server 4.0.0, as the SAML support is no longer out of the box (but in the cas-server-support-saml module), the SamlService must be explicitely registered with its serializer : SamlServiceSerializer.

CAS 3.4.x and Prior Memcached Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/jee 
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

    <!-- Ticket Registry -->
    <bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.MemCacheTicketRegistry">
        <!-- List of hostname:port pairs -->
    	<constructor-arg index="0">
    		<list>
    			<value>machine1:11211</value>
    			<value>machine2:11211</value>
    		</list>
    	</constructor-arg>
 
        <!-- TGT timeout in seconds -->
    	<constructor-arg index="1" type="int" value="21600" />
 
        <!-- ST timeout in seconds -->
    	<constructor-arg index="2" type="int" value="300" />
    </bean>
</beans>

Security

Memcached by default does not provide for authentication/authorization or a secure transport.  You should discuss with your Network team on the best way to secure the data being sent to the memcache servers.  An SSH tunnel is a reasonable solution to the secure transport problem.  There is rudimentary support for SASL

High Availability Considerations

Memcached does not provide for replication by design, but the client is tolerant to node failures with failureMode="Redistribute".  In this mode, a write failure will simply cause the client to rekey the item and write it to an available node.  It will continue to read and write from a backup node until the dead client becomes available, at which time if the key is still available in that node it will supercede the value known to the backup node.

It may be helpful to examine the effect of the behavior above on a CAS SSO session.  Consider a single CAS server that has a pool of 3 memcached nodes, memcached-[1|2|3], all of which are initially available.

  1. User authenticates and obtains TGT-123 which is written to memcached-2 based on the hashing algorithm applied to the key (TGT string)
  2. User requests a service ticket from TGT-123, which causes a read from memcached-2 to get the TGT and write to memcached-1 for the ST (it's worth repeating that the node chosen is based upon the key in a more-or-less random fashion, so subsequent tickets will likely hash to distinct memcached nodes)
  3. Some time passes during which memcached-2 becomes unavailable is removed from the pool of available nodes as known to the CAS server
  4. User subsequently presents TGT-123 (via CASTGC browser cookie) to request another service ticket
  5. The client is aware that memcached-2 is dead and rehashes the key to another active node in the pool, say memcached-3.  Of course this node does not contain the user's TGT, which has the effect of forcing the user to reauthenticate.
  6. User reauthenticates and gets a new TGT, TGT-676, which is written to memcached-1.
  7. At some later date memcached-3 comes back online and the original TGT, TGT-123, is still known to the cache.  Since the user's CASTGC cookie has subsequently changed to a new value, TGT-676, due to reauthentication, TGT-123 is effectively orphaned and will be expired naturally due to the TGT expiration policy.
While the above flow is not the only failure mode that can occur when a memcached node becomes unavailable, it's arguably by far the most common failure mode.

 

Memcached Failure Mode is Graceful

In most cases a memcached node failure results in user reauthentication, which in most cases would be an acceptable and graceful failure mode. This failure mode may not be acceptable to deployments that rely on long-term authentication tokens (i.e. "Remember Me") to ensure a long duration between subsequent authentications.

Ticket Cleanup

Memcached, like other cache-based storage mechanisms, inserts all items into the cache with an expiration period after which time the item is marked as expired and the storage is reclaimed. In this view Memcached like other caches is self cleaning and does not require (or support) the RegistryCleaner component.

Couchbase

As Couchbase (persistent NoSQL database) is natively supporting the Memcached protocol, the MemCacheTicketRegistry can be used to store/retrieve tickets in Couchbase.