<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="cas"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>CAS Authentication</title>
    <section xml:id="cas-overview">
        <title>Overview</title>
        <para>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
            initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple
            to understand, platform independent, and supports proxy capabilities. Spring Security
            fully supports CAS, and provides an easy migration path from single-application
            deployments of Spring Security through to multiple-application deployments secured by an
            enterprise-wide CAS server.</para>
        <para>You can learn more about CAS at <literal>http://www.ja-sig.org/cas</literal>. You will
            also need to visit this site to download the CAS Server files.</para>
    </section>
    <section xml:id="cas-how-it-works">
        <info>
            <title>How CAS Works</title>
        </info>
        <para>Whilst the CAS web site contains documents that detail the architecture of CAS, we
      present the general overview again here within the context of Spring Security. Spring Security
      3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4.</para>
        <para>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is
            simply a standard WAR file, so there isn't anything difficult about setting up your
            server. Inside the WAR file you will customise the login and other single sign on pages
            displayed to users.</para>
        <para>When deploying a CAS 3.4 server, you will also need to specify an
        <literal>AuthenticationHandler</literal> in the
        <filename>deployerConfigContext.xml</filename> included with CAS. The
        <literal>AuthenticationHandler</literal> has a simple method that returns a boolean as to
      whether a given set of Credentials is valid. Your <literal>AuthenticationHandler</literal>
      implementation will need to link into some type of backend authentication repository, such as
      an LDAP server or database. CAS itself includes numerous
        <literal>AuthenticationHandler</literal>s out of the box to assist with this. When you
      download and deploy the server war file, it is set up to successfully authenticate users who
      enter a password matching their username, which is useful for testing.</para>
        <para>Apart from the CAS server itself, the other key players are of course the secure web
      applications deployed throughout your enterprise. These web applications are known as
      "services". There are three types of services. Those that authenticate service tickets, those that
      can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket
      differs because the list of proxies must be validated and often times a proxy ticket can be reused.</para>

  <section xml:id="cas-sequence">
    <title>Spring Security and CAS Interaction Sequence</title>

    <para>The basic interaction between a web browser, CAS server and a
    Spring Security-secured service is as follows:</para>

    <orderedlist inheritnum="ignore" continuation="restarts">
      <listitem>
        <para>The web user is browsing the service's public pages. CAS or
        Spring Security is not involved.</para>
      </listitem>

      <listitem>
        <para>The user eventually requests a page that is either secure or
        one of the beans it uses is secure. Spring Security's
        <classname>ExceptionTranslationFilter</classname> will detect the
        <classname>AccessDeniedException</classname> or <classname>AuthenticationException</classname>.</para>
      </listitem>

      <listitem>
        <para>Because the user's <interfacename>Authentication</interfacename> object (or lack
            thereof) caused an <classname>AuthenticationException</classname>, the
              <classname>ExceptionTranslationFilter</classname> will call the configured
              <interfacename>AuthenticationEntryPoint</interfacename>. If using CAS, this will be
            the <classname>CasAuthenticationEntryPoint</classname> class.</para>
      </listitem>

      <listitem>
        <para>The <classname>CasAuthenticationEntryPoint</classname> will redirect the user's browser
            to the CAS server. It will also indicate a <literal>service</literal> parameter, which
            is the callback URL for the Spring Security service (your application). For example, the
            URL to which the browser is redirected might be
              <literal>https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check</literal>.</para>
      </listitem>

      <listitem>
        <para>After the user's browser redirects to CAS, they will be
        prompted for their username and password. If the user presents a
        session cookie which indicates they've previously logged on, they
        will not be prompted to login again (there is an exception to this
        procedure, which we'll cover later). CAS will use the
        <interfacename>PasswordHandler</interfacename> (or
        <interfacename>AuthenticationHandler</interfacename> if using CAS 3.0)
        discussed above to decide whether the username and password is
        valid.</para>
      </listitem>

      <listitem>
        <para>Upon successful login, CAS will redirect the user's browser
        back to the original service. It will also include a
        <literal>ticket</literal> parameter, which is an opaque string
        representing the "service ticket". Continuing our earlier example,
        the URL the browser is redirected to might be
        <literal>https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</literal>.</para>
      </listitem>

      <listitem>
        <para>Back in the service web application, the <classname>CasAuthenticationFilter</classname> is
            always listening for requests to <literal>/j_spring_cas_security_check</literal> (this
            is configurable, but we'll use the defaults in this introduction). The processing filter
            will construct a <classname>UsernamePasswordAuthenticationToken</classname> representing the
            service ticket. The principal will be equal to
              <literal>CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</literal>, whilst the credentials
            will be the service ticket opaque value. This authentication request will then be handed
            to the configured <interfacename>AuthenticationManager</interfacename>.</para>
      </listitem>

      <listitem>
        <para>The <interfacename>AuthenticationManager</interfacename> implementation
        will be the <classname>ProviderManager</classname>, which is in turn
        configured with the <classname>CasAuthenticationProvider</classname>.
        The <classname>CasAuthenticationProvider</classname> only responds to
        <classname>UsernamePasswordAuthenticationToken</classname>s containing
        the CAS-specific principal (such as
        <literal>CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</literal>)
        and <classname>CasAuthenticationToken</classname>s (discussed
        later).</para>
      </listitem>

      <listitem>
        <para><classname>CasAuthenticationProvider</classname> will validate the service ticket using a
            <interfacename>TicketValidator</interfacename> implementation. This will typically be a
            <classname>Cas20ServiceTicketValidator</classname> which is one of the classes
            included in the CAS client library. In the event the application needs to validate proxy tickets, the
            <classname>Cas20ProxyTicketValidator</classname> is used. The
            <interfacename>TicketValidator</interfacename> makes an HTTPS request to the CAS server in order to
            validate the service ticket. It may also include a proxy callback URL, which is included in this example:
            <literal>https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor</literal>.
            </para>
      </listitem>

      <listitem>
        <para>Back on the CAS server, the validation request will be
        received. If the presented service ticket matches the service URL
        the ticket was issued to, CAS will provide an affirmative response
        in XML indicating the username. If any proxy was involved in the
        authentication (discussed below), the list of proxies is also
        included in the XML response.</para>
      </listitem>

      <listitem>
        <para>[OPTIONAL] If the request to the CAS validation service included the proxy callback
            URL (in the <literal>pgtUrl</literal> parameter), CAS will include a
              <literal>pgtIou</literal> string in the XML response. This <literal>pgtIou</literal>
            represents a proxy-granting ticket IOU. The CAS server will then create its own HTTPS
            connection back to the <literal>pgtUrl</literal>. This is to mutually authenticate the
            CAS server and the claimed service URL. The HTTPS connection will be used to send a
            proxy granting ticket to the original web application. For example,
              <literal>https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</literal>.</para>
      </listitem>

      <listitem>
        <para>The <classname>Cas20TicketValidator</classname> will parse the XML received from the
            CAS server. It will return to the <classname>CasAuthenticationProvider</classname> a
              <literal>TicketResponse</literal>, which includes the username (mandatory), proxy list
            (if any were involved), and proxy-granting ticket IOU (if the proxy callback was
            requested).</para>
      </listitem>

      <listitem>
        <para>Next <literal>CasAuthenticationProvider</literal> will call
        a configured <literal>CasProxyDecider</literal>. The
        <literal>CasProxyDecider</literal> indicates whether the proxy
        list in the <literal>TicketResponse</literal> is acceptable to the
        service. Several implementations are provided with Spring
        Security: <literal>RejectProxyTickets</literal>,
        <literal>AcceptAnyCasProxy</literal> and
        <literal>NamedCasProxyDecider</literal>. These names are largely
        self-explanatory, except <literal>NamedCasProxyDecider</literal>
        which allows a <literal>List</literal> of trusted proxies to be
        provided.</para>
      </listitem>

      <listitem>
        <para><classname>CasAuthenticationProvider</classname> will next
        request a <interfacename>AuthenticationUserDetailsService</interfacename> to load the
        <interfacename>GrantedAuthority</interfacename> objects that apply to the user
        contained in the <interfacename>Assertion</interfacename>.</para>
      </listitem>

      <listitem>
        <para>If there were no problems,
        <classname>CasAuthenticationProvider</classname> constructs a
        <classname>CasAuthenticationToken</classname> including the details
        contained in the <interfacename>TicketResponse</interfacename> and the
        <interfacename>GrantedAuthority</interfacename>s.</para>
      </listitem>

      <listitem>
        <para>Control then returns to
        <classname>CasAuthenticationFilter</classname>, which places the created
        <classname>CasAuthenticationToken</classname> in the security context.</para>
      </listitem>

      <listitem>
        <para>The user's browser is redirected to the original page that
        caused the <classname>AuthenticationException</classname> (or a
          <link xlink:href="#form-login-flow-handling">custom destination</link> depending on
          the configuration).</para>
      </listitem>
    </orderedlist>

    <para>It's good that you're still here! Let's now look at how this is configured</para>
  </section>

    </section>
    <section xml:id="cas-client">
        <info>
            <title>Configuration of CAS Client</title>
        </info>
        <para>The web application side of CAS is made easy due to Spring Security. It is assumed you
            already know the basics of using Spring Security, so these are not covered again below.
            We'll assume a namespace based configuration is being used and add in the CAS beans as
            required. Each section builds upon the previous section. A full
            <link xlink:href="#cas-sample">CAS sample application</link> can be found in the Spring
            Security Samples.</para>
        <section xml:id="cas-st">
            <info>
                <title>Service Ticket Authentication</title>
            </info>
            <para>This section describes how to setup Spring Security to authenticate Service Tickets. Often times
                this is all a web application requires. You will need to add a <classname>ServiceProperties</classname>
                bean to your application context. This represents your CAS service:</para>
            <para> <programlisting language="xml"><![CDATA[
  <bean id="serviceProperties"
        class="org.springframework.security.cas.ServiceProperties">
    <property name="service"
        value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/>
    <property name="sendRenew" value="false"/>
  </bean>]]>
    </programlisting> </para>
            <para>The <literal>service</literal> must equal a URL that will be monitored by the
                <literal>CasAuthenticationFilter</literal>. The <literal>sendRenew</literal> defaults to
                false, but should be set to true if your application is particularly sensitive. What
                this parameter does is tell the CAS login service that a single sign on login is
                unacceptable. Instead, the user will need to re-enter their username and password in
                order to gain access to the service.</para>
            <para>The following beans should be configured to commence the CAS authentication process
                (assuming you're using a namespace configuration):</para>
            <para> <programlisting language="xml"><![CDATA[
  <security:http entry-point-ref="casEntryPoint">
   ...
     <security:custom-filter position="CAS_FILTER" ref="casFilter" />
  </security:http>

  <bean id="casFilter"
        class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
  </bean>

  <bean id="casEntryPoint"
      class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    <property name="loginUrl" value="https://localhost:9443/cas/login"/>
    <property name="serviceProperties" ref="serviceProperties"/>
  </bean>
]]>
    </programlisting> </para>
        <para>For CAS to operate, the <classname>ExceptionTranslationFilter</classname> must have
            its <literal>authenticationEntryPoint</literal> property set to the
            <classname>CasAuthenticationEntryPoint</classname> bean. This can easily be done using
            <link xlink:href="#ns-entry-point-ref"><literal>entry-point-ref</literal></link> as is
            done in the example above. The <classname>CasAuthenticationEntryPoint</classname> must refer to the
            <classname>ServiceProperties</classname> bean (discussed above), which provides the URL
            to the enterprise's CAS login server. This is where the user's browser will be
            redirected.</para>
        <para>The <classname>CasAuthenticationFilter</classname> has very similar properties to the
            <classname>UsernamePasswordAuthenticationFilter</classname> (used for form-based
            logins). You can use these properties to customize things like behavior for authentication
            success and failure.</para>
        <para>Next you need to add a <classname>CasAuthenticationProvider</classname> and its
            collaborators: <programlisting language="xml"><![CDATA[
  <security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="casAuthenticationProvider" />
  </security:authentication-manager>

  <bean id="casAuthenticationProvider"
      class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    <property name="authenticationUserDetailsService">
      <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
        <constructor-arg ref="userService" />
      </bean>
    </property>
    <property name="serviceProperties" ref="serviceProperties" />
    <property name="ticketValidator">
      <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
        <constructor-arg index="0" value="https://localhost:9443/cas" />
      </bean>
    </property>
    <property name="key" value="an_id_for_this_auth_provider_only"/>
  </bean>

  <security:user-service id="userService">
    <security:user name="joe" password="joe" authorities="ROLE_USER" />
    ...
  </security:user-service>]]>
      </programlisting> The <classname>CasAuthenticationProvider</classname> uses a
            <interfacename>UserDetailsService</interfacename> instance to load the authorities for a
            user, once they have been authenticated by CAS. We've shown a simple in-memory setup
            here. Note that the <classname>CasAuthenticationProvider</classname> does not actually use
            the password for authentication, but it does use the authorities.</para>
         <para>The beans are all reasonably self-explanatory if you refer back to the
              <link xlink:href="#cas-how-it-works">How CAS Works</link> section.</para>
         <para>This completes the most basic configuration for CAS. If you haven't made any
            mistakes, your web application should happily work within the
            framework of CAS single sign on. No other parts of Spring Security
            need to be concerned about the fact CAS handled authentication. In the following sections
            we will discuss some (optional) more advanced configurations.</para>
        </section>
        <section xml:id="cas-singlelogout">
            <info>
                <title>Single Logout</title>
            </info>
            <para>The CAS protocol supports Single Logout and can be easily added to your Spring
                Security configuration. Below are updates to the Spring Security configuration
                that handle Single Logout <programlisting language="xml"><![CDATA[
  <security:http entry-point-ref="casEntryPoint">
  ...
    <security:logout logout-success-url="/cas-logout.jsp"/>
    <security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
    <security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
  </security:http>

  <!-- This filter handles a Single Logout Request from the CAS Server -->
  <bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
  <!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
  <bean id="requestSingleLogoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg value="https://localhost:9443/cas/logout"/>
    <constructor-arg>
      <bean class=
          "org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
    </constructor-arg>
    <property name="filterProcessesUrl" value="/j_spring_cas_security_logout"/>
  </bean>
            ]]></programlisting> The <literal>logout</literal> element logs the user out of the local application, but
                does not terminate the session with the CAS server or any other applications that have been logged
                into. The <literal>requestSingleLogoutFilter</literal> filter will allow the url of
                <literal>/spring_security_cas_logout</literal> to be requested to redirect the application to the
                configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the
                services that were signed into. The <literal>singleLogoutFilter</literal> handles the Single Logout
                request by looking up the <literal>HttpSession</literal> in a static <interfacename>Map</interfacename>
                and then invalidating it.</para>
            <para>It might be confusing why both the <literal>logout</literal> element and the
                <literal>singleLogoutFilter</literal> are needed. It is considered best practice to logout locally
                first since the <literal>SingleSignOutFilter</literal> just stores the
                <interfacename>HttpSession</interfacename> in a static <interfacename>Map</interfacename> in order to
                call invalidate on it. With the configuration above, the flow of logout would be:
                <orderedlist inheritnum="ignore" continuation="restarts">
                    <listitem>The user requests <literal>/j_spring_security_logout</literal> which would log the user
                        out of the local application and send the user to the logout success page.</listitem>
                    <listitem>The logout success page, <literal>/cas-logout.jsp</literal>, should instruct the user
                        to click a link pointing to <literal>/j_spring_cas_security_logout</literal> in order to logout
                        out of all applications.</listitem>
                    <listitem>When the user clicks the link, the user is redirected to the CAS single logout URL
                        (<literal>https://localhost:9443/cas/logout</literal>).</listitem>
                    <listitem>On the CAS Server side, the CAS single logout URL then submits single logout requests to
                        all the CAS Services. On the CAS Service side, JASIG's
                        <classname>SingleSignOutFilter</classname> processes the logout request by invaliditing the
                        original session.</listitem>
                </orderedlist>
            </para>
            <para>The next step is to add the following to your web.xml
                <programlisting language="xml"><![CDATA[
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <listener>
    <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
  </listener>]]></programlisting></para>
            <para>When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is
                recommended to add the <classname>CharacterEncodingFilter</classname> to ensure that the character
                encoding is correct when using the <classname>SingleSignOutFilter</classname>. Again, refer to JASIG's
                documentation for details. The <classname>SingleSignOutHttpSessionListener</classname> ensures that
                when an <interfacename>HttpSession</interfacename> expires, the mapping used for single logout is
                removed.</para>
        </section>
        <section xml:id="cas-pt-client">
                <info>
                    <title>Authenticating to a Stateless Service with CAS</title>
                </info>
                <para>This section describes how to authenticate to a service using CAS. In other words,
                    this section discusses how to setup a client that uses a service that authenticates with
                    CAS. The next section describes how to setup a stateless service to Authenticate
                    using CAS.</para>
                <section xml:id="cas-pt-client-config">
                    <info>
                        <title>Configuring CAS to Obtain Proxy Granting Tickets</title>
                    </info>
                    <para>In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket
                        (PGT). This section describes how to configure Spring Security to obtain a PGT building upon then
                        <link xlink:href="cas-st">Service Ticket Authentication</link> configuration.</para>
                    <para>The first step is to include a <classname>ProxyGrantingTicketStorage</classname> in your Spring Security
                        configuration. This is used to store PGT's that are obtained by the
                        <classname>CasAuthenticationFilter</classname> so that they can be used to obtain proxy tickets. An example
                        configuration is shown below <programlisting language="xml"><![CDATA[
  <!--
    NOTE: In a real application you should not use an in memory implementation. You will also want
          to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup()
  -->
  <bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>
]]></programlisting></para>
                    <para>The next step is to update the <classname>CasAuthenticationProvider</classname> to be able to obtain proxy
                        tickets. To do this replace the <classname>Cas20ServiceTicketValidator</classname> with a
                        <classname>Cas20ProxyTicketValidator</classname>. The <literal>proxyCallbackUrl</literal> should be set to
                        a URL that the application will receive PGT's at. Last, the configuration should also reference the
                        <classname>ProxyGrantingTicketStorage</classname> so it can use a PGT to obtain proxy tickets.
                        You can find an example of the configuration changes that should be made below.
<programlisting language="xml"><![CDATA[
  <bean id="casAuthenticationProvider"
      class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    ...
    <property name="ticketValidator">
      <bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
        <constructor-arg value="https://localhost:9443/cas"/>

        <property name="proxyCallbackUrl"
            value="https://localhost:8443/cas-sample/j_spring_cas_security_proxyreceptor"/>
        <property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
      </bean>
    </property>
  </bean>
]]></programlisting></para>
                    <para>The last step is to update the <classname>CasAuthenticationFilter</classname> to accept PGT and to store them
                        in the <classname>ProxyGrantingTicketStorage</classname>. It is important the the <literal>proxyReceptorUrl</literal>
                        matches the <literal>proxyCallbackUrl</literal> of the <classname>Cas20ProxyTicketValidator</classname>. An example
                        configuration is shown below.
<programlisting language="xml"><![CDATA[
  <bean id="casFilter"
        class="org.springframework.security.cas.web.CasAuthenticationFilter">
    ...
    <property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
    <property name="proxyReceptorUrl" value="/j_spring_cas_security_proxyreceptor"/>
  </bean>
]]></programlisting></para>
                </section>
                <section xml:id="cas-pt-client-sample">
                    <info>
                        <title>Calling a Stateless Service Using a Proxy Ticket</title>
                    </info>
                    <para>Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate
                        to a stateless service. The <link xlink:href="#cas-sample">CAS sample application</link> contains a working example in
                        the <classname>ProxyTicketSampleServlet</classname>. Example code can be found below:
<programlisting language="xml"><![CDATA[
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // NOTE: The CasAuthenticationToken can also be obtained using
    // SecurityContextHolder.getContext().getAuthentication()
    final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
    // proxyTicket could be reused to make calls to the CAS service even if the
    // target url differs
    final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);

    // Make a remote call using the proxy ticket
    final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
    String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
    ...
  }
]]></programlisting></para>
                </section>
        </section>
        <section xml:id="cas-pt">
            <info>
                <title>Proxy Ticket Authentication</title>
            </info>
                <para>The <classname>CasAuthenticationProvider</classname> distinguishes
                    between stateful and stateless clients. A stateful client is
                    considered any that submits to the <literal>filterProcessUrl</literal> of the
                    <classname>CasAuthenticationFilter</classname>. A stateless client is any that
                    presents an authentication request to <classname>CasAuthenticationFilter</classname>
                    on a URL other than the <literal>filterProcessUrl</literal>.</para>
                <para>Because remoting protocols have no way of presenting themselves
                    within the context of an <classname>HttpSession</classname>, it isn't
                    possible to rely on the default practice of storing the security context in the
                    session between requests. Furthermore, because the CAS server invalidates a
                    ticket after it has been validated by the <literal>TicketValidator</literal>,
                    presenting the same proxy ticket on subsequent requests will not
                    work.</para>
                <para>One obvious option is to not use CAS at all for remoting
                    protocol clients. However, this would eliminate many of the desirable
                    features of CAS. As a middle-ground, the
                    <literal>CasAuthenticationProvider</literal> uses a
                    <literal>StatelessTicketCache</literal>. This is used solely for stateless clients
                    which use a principal equal to
                    <literal>CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER</literal>. What
                    happens is the <literal>CasAuthenticationProvider</literal> will store
                    the resulting <literal>CasAuthenticationToken</literal> in the
                    <literal>StatelessTicketCache</literal>, keyed on the proxy ticket.
                    Accordingly, remoting protocol clients can present the same proxy
                    ticket and the <literal>CasAuthenticationProvider</literal> will not
                    need to contact the CAS server for validation (aside from the first
                    request). Once authenticated, the proxy ticket could be used for URLs other than the
                    original target service.</para>
                <para>This section builds upon the previous sections to accomodate proxy ticket authentication.
                    The first step is to specify to authenticate all artifacts as shown below.
<programlisting language="xml"><![CDATA[
  <bean id="serviceProperties"
        class="org.springframework.security.cas.ServiceProperties">
    ...
    <property name="authenticateAllArtifacts" value="true"/>
  </bean>
]]></programlisting></para>
                <para>The next step is to specify <literal>serviceProperties</literal> and the
                    <literal>authenticationDetailsSource</literal> for the <classname>CasAuthenticationFilter</classname>.
                    The <literal>serviceProperties</literal> property instructs the
                    <classname>CasAuthenticationFilter</classname> to attempt to authenticate all artifacts instead of only
                    ones present on the <literal>filterProcessUrl</literal>. The
                    <classname>ServiceAuthenticationDetailsSource</classname> creates a
                    <interfacename>ServiceAuthenticationDetails</interfacename> that ensures the current URL, based
                    upon the <literal>HttpServletRequest</literal>, is used as the service URL when validating the ticket.
                    The method for generating the service URL can be customized by injecting a custom
                    <literal>AuthenticationDetailsSource</literal> that returns a custom
                    <interfacename>ServiceAuthenticationDetails</interfacename>.<programlisting language="xml"><![CDATA[
  <bean id="casFilter"
      class="org.springframework.security.cas.web.CasAuthenticationFilter">
    ...
    <property name="serviceProperties" ref="serviceProperties"/>
    <property name="authenticationDetailsSource">
      <bean class=
        "org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
        <constructor-arg ref="serviceProperties"/>
      </bean>
    </property>
  </bean>
]]></programlisting></para>
                <para>You will also need to update the <classname>CasAuthenticationProvider</classname> to handle proxy tickets.
                    To do this replace the <classname>Cas20ServiceTicketValidator</classname> with a
                    <classname>Cas20ProxyTicketValidator</classname>. You will need to configure the
                    <literal>statelessTicketCache</literal> and which proxies you want to accept. You can find an example of the updates
                    required to accept all proxies below.
<programlisting language="xml"><![CDATA[
  <bean id="casAuthenticationProvider"
      class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    ...
    <property name="ticketValidator">
      <bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
        <constructor-arg value="https://localhost:9443/cas"/>
        <property name="acceptAnyProxy" value="true"/>
      </bean>
    </property>
    <property name="statelessTicketCache">
      <bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
        <property name="cache">
          <bean class="net.sf.ehcache.Cache"
              init-method="initialise" destroy-method="dispose">
            <constructor-arg value="casTickets"/>
            <constructor-arg value="50"/>
            <constructor-arg value="true"/>
            <constructor-arg value="false"/>
            <constructor-arg value="3600"/>
            <constructor-arg value="900"/>
          </bean>
        </property>
      </bean>
    </property>
  </bean>
]]></programlisting></para>
        </section>
    </section>
</chapter>
