CAS-ify a Java Application

Instructions and sample code for using the CAS Java client are below and are meant to give you a sense of the level of work required to integrate CAS into a Java web application. Many commercial and open source products used in higher education that have built-in support for CAS base that support on the Java CAS client. See the CAS Java Client page for a complete set of integration instructions including tips on using Maven and Spring Security

Note: it is important to use the current version of a given CAS client to ensure the code includes the latest security fixes. The current version of the CAS Java client is 3.6.1.

  • Add code to your application to retrieve the UNI

    import org.jasig.cas.client.authentication.AttributePrincipal;
    
    public class YourServlet extends HttpServiet 
    {
    ...
      public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException 
      { 
        ...  
        // The CAS client puts the Principal into the HttpServletRequest:
        AttributePrincipal principal = (AttributePrincipal)req.getUserPrincipal();
        // Check for null values each step of the way, then:
        String uni = principal.getName();
        ...etc.
      }
      ...
    }
  • (Optional) Add code to your application to retrieve other principal attributes:

    import org.jasig.cas.client.authentication.AttributePrincipal;
    import java.util.Date;
    ...
    public class YourServlet extends HttpServiet 
    {
      public static String STAFF_AFFILIATION = "CUstaff";
      public static String AFFILIATION_ATTRIBUTE_NAME = "affiliation";
      public static String PWD_CHG_DATE_ATTRIBUTE_NAME = "lastPasswordChangeDate";
      public static String EMAIL_ATTRIBUTE_NAME = "mail";
      ...
      public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException 
      { 
        ...  
        // Check if the user has a staff affil:
        AttributePrincipal principal = (AttributePrincipal)req.getUserPrincipal();
        Map attributes = (principal==null) 
          ? new HashMap() 
          : principal.getAttributes();
    
        // Check for null values at each step. Then:
        List affiliations = (List)attributes.get(AFFILIATION_ATTRIBUTE_NAME);
        // The affiliation attribute is multi-valued.
        boolean isStaff = ( affiliations==null ) 
          ? false 
          : affiliations.contains(STAFF_AFFILIATION);
    
        // The email address is a single-valued attribute:
        String email = (String) attributes.get(EMAIL_ATTRIBUTE_NAME);
         ...etc.
    
        // The CAS client returns lastPasswordChangeDate as a java.util.Date:
        Date lastPasswordChangeDate = (Date) attributes.get(PWD_CHG_DATE_ATTRIBUTE_NAME);
         ...etc.
    
      }
    }
  • Add CAS servlet filters to web.xml, using values for the local CAS server

    The terms "filter" and "servlet filter" can refer to the <filter> element in web.xml or to the Java class named by the <filter> element that implements filter behavior. Here it refers to the <filter> element that is added to web.xml. You will need to define these 3 filters:

    • CAS Authentication Filter
    • CAS Validation Filter
    • CAS HttpServletRequestWrapper Filter

     

    You may also want to declare other filters (see the CAS Client documentation.) In addition, <filter-mapping> elements must be added to web.xml to make sure that incoming requests are sent to the correct filters. See the web.xml fragments below, as well as the CAS Client documentation for instructions on configuring filters for the various CAS protocols.


    web.xml

    If the web application only needs the UNI, you can use the CAS 2 protocol and the lightweight AuthenticationFilter and Cas20ProxyReceivingTicketValidationFilter combination as follows:

     <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.columbia.edu/cas/login</param-value>
        </init-param>
        <init-param>
          <param-name>serverName</param-name>
          <param-value>https://your-hostname</param-value>  <-- hostname of registered URLs
        </init-param>
      </filter>
      <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://cas.columbia.edu/cas/</param-value>
        </init-param>
        <init-param>
          <param-name>serverName</param-name>
          <param-value>https://your-hostname</param-value> <-- hostname of registered URLs
        </init-param>
        <init-param>
          <param-name>artifactParameterName</param-name>
          <param-value>ticket</param-value>
        </init-param>
        <init-param>
          <param-name>redirectAfterValidation</param-name>
          <param-value>true</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> 
    
    

     

    If the application needs additional attributes besides the UNI, like first name, last name, and LDAP affiliations, you can use either the CAS 3 or SAML 1.1 protocols. CAS 3 is simpler and is preferred. See the examples below:

    CAS 3 filters:

    <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.columbia.edu/cas/login</param-value>
      </init-param>
      <init-param>
        <param-name>service</param-name>
        <param-value>https://your-hostname/your-context/yourPath</param-value>   <-- Your registered URL
      </init-param>
      <init-param>
        <param-name>artifactParameterName</param-name>
        <param-value>ticket</param-value>
      </init-param>
      <init-param>
        <param-name>serviceParameterName</param-name>
        <param-value>service</param-value>
      </init-param>
    </filter>
    
    <filter>
      <filter-name>CAS Validation Filter</filter-name>
      <filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class>
      <init-param>
        <param-name>casServerUrlPrefix</param-name>
        <param-value>https://cas.columbia.edu/cas/</param-value>
      </init-param>
      <init-param>
        <param-name>service</param-name>
        <param-value>https://your-hostname/your-context/yourPath</param-value>
      </init-param>
      <init-param>
        <param-name>artifactParameterName</param-name>
        <param-value>ticket</param-value>
      </init-param>
      <init-param>
        <param-name>serviceParameterName</param-name>
        <param-value>service</param-value>
      </init-param>
      <init-param>
        <param-name>redirectAfterValidation</param-name>
        <param-value>true</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>
    
     <!-- Other filters as needed -->

     

    SAML 1.1 filters:

     <filter> 
        <filter-name>CAS Authentication Filter</filter-name> 
        <filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class> 
         <init-param> 
           <param-name>casServerLoginUrl</param-name> 
           <param-value>https://cas.columbia.edu/cas/login</param-value> 
         </init-param> 
         <init-param> 
           <param-name>serverName</param-name> 
           <param-value>https://your-hostname</param-value>  <-- hostname of registered URLs
         </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.columbia.edu/cas/</param-value> 
        </init-param> 
        <init-param> 
          <param-name>serverName</param-name> 
          <param-value>https://your-hostname</param-value> <-- hostname of registered URLs
        </init-param> 
        <init-param> 
          <param-name>artifactParameterName</param-name> 
          <param-value>SAMLArt</param-value> 
        </init-param> 
        <init-param> 
          <param-name>serviceParameterName</param-name> 
          <param-value>TARGET</param-value> 
        </init-param> 
        <init-param> 
          <param-name>redirectAfterValidation</param-name> 
          <param-value>true</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> 
    
      <!-- Other filters as needed -->

     

    Filter Mappings:

    The filter mappings below send all default context requests ("/") to the 3 filters defined in the examples above.

      <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 HttpServletRequest Wrapper Filter</filter-name> 
        <url-pattern>/*</url-pattern> 
      </filter-mapping>
    
        <!-- 
          Other filter mappings as needed. 
          Ordering of filter mappings is important. 
        -->

     

  • (Optional): Print debugging information in the log

    To print the service ticket validation response in the CAS client log, add the following logger element to your log4j2.xml (or a similar configuration in your logging framework of choice):

      <Loggers>
      ...
        <AsyncLogger name="org.jasig.cas.client" level="debug" additivity="false">
          <Appender-Ref ref="[YOUR-APPENDER]" />
        </AsyncLogger>
      ...
      </Loggers> 
    
    
    
  • Add client jars to the application classpath (but best to let a build tool like Maven do this for you.)

    WEB-INF/lib
          cas-client-core-3.6.1.jar
          cas-client-support-saml-3.6.1.jar [for SAML 1.1 support]
          jackson-annotations-2.10.0.jar
          jackson-core-2.8.8.jar
          jackson-databind-2.8.8.1.jar
          joda-time-2.9.9.jar
          log4j-1.2.17.jar
          slf4j-api-1.7.28.jar
          slf4j-log4j12-1.7.21.jar
    
    
  • Result:

    • Application users are forced to log in thru CAS.
    • The UNI and as well as other user attributes are made available to the application via the AttributePrincipal.
    • If appropriate, the SSO session is honored.