CAS client authentication methods

Introduction

CAS (Central Authentication Service) is a web-based authentication appliance that is meant to provide a single sign-on solution for UW web sites and applications. CAS accepts your !WatIAM credentials and authenticates you against UW's Active Directory, whereupon CAS informs the calling application of your identity. At no time are your userid and password accessible to the calling application. We recommend you use CAS in all instances where you must authenticate UW community members in order for them to access your web site or application. The following documentation will instruct you on how to configure your particular web environment to make use of CAS.

Requirements

Cookies must be enabled in your browser for CAS to function properly.

URLs

For any CAS client API you choose to make use of, you will have to provide the CAS server URL:

   Production server hostname: cas.uwaterloo.ca
   Development server hostname: cas-dev.uwaterloo.ca
   Port: 443

   base URL: https://cas.uwaterloo.ca/cas
   login URL: https://cas.uwaterloo.ca/cas/login
   logout URL: https://cas.uwaterloo.ca/cas/logout
   serviceValidate URL: https://cas.uwaterloo.ca/cas/serviceValidate
   samlValidate URL: https://cas.uwaterloo.ca/cas/samlValidate

Substitute cas-dev.uwaterloo.ca for cas.uwaterloo.ca in any of the above URLs to use the development server. New versions of CAS and/or new features will be tested on the development server, which means that there may be intermittent service outages, but we try to keep those to a minimum.

SSL certificates

cas.uwaterloo.ca (and the development and test servers) uses a Globalsign SSL certificate signed against a Globalsign intermediate CA certificate. If you have a Java servlet container that uses a cacerts file, or use mod_auth_cas or phpCAS with httpd, please make sure you use a recent __globalsignchain.crt__ - see the comment about intermediates on IST's Self-service GlobalSign SSL certificates page.

CAS timeouts

There are default timeouts involved for both the CAS server tickets and the individual client-based modules/APIs. Unlike Basic authentication, once authenticated to CAS, a session does not last until the browser is closed. Typically, once you authenticate, a ticket-granting ticket (TGT) is generated and stored on the CAS server and a service ticket is generated against that and is used by the client to verify your authenticated identity. If that TGT is not used for a period of 2 hours (e.g. no service tickets are requested from the CAS server in that span) then the ticket is destroyed, and if your module/API requests another service ticket from the CAS server, you will be prompted to re-authenticate, thus creating a new TGT. The 2 hour limit is an idle timeout, not a hard timeout. If you used CAS-protected services every hour throughout the day, your TGT would continue to be valid.

Attribute Release via SAML

CAS has the ability to release user-specific attributes to the calling application via the SAML standard. These attributes are gleaned from the Active Directory user DN search, and include:

   * dn
   * cn
   * displayName
   * givenName
   * name
   * sn
   * mail
   * physicalDeliveryOfficeName
   * telephoneNumber
   * department

The attribute

   * memberOf

can be released to certain applications upon request. Attribute release is not enabled by default for applications authenticating from off-campus. If you would like to request access to the memberOf attribute, please contact rt@uwaterloo.ca.

See https://wiki.jasig.org/display/CASUM/SAML+1.1 for further information on the SAML protocol as it related to CAS.

mod_auth_cas

mod_auth_cas is a pluggable authentication module for the Apache httpd server.

  1. Fetch the source and build:
    cd /tmp ; svn export https://source.jasig.org/cas-clients/mod_auth_cas/trunk
    cd /tmp/trunk ; /usr/sbin/apxs -c src/mod_auth_cas.c
    
    
  2. Become root and install the module (the default destination is /usr/lib/httpd/modules):
    sudo /usr/sbin/apxs -lssl -lcurl -i src/mod_auth_cas.la
    
    
  3. Create the CAS cookie directory (make sure the location is not volatile, for if the directory disappears, mod_auth_cas stops working and httpd won't survive a restart):
    mkdir /var/tmp/cas
    chown apache:apache /var/tmp/cas
    
    
  4. Install either or both of the aforementioned CA certificate files in an appropriate location, and create a mod_auth_cas.conf configuration file with the following contents:
    LoadModule auth_cas_module modules/mod_auth_cas.so
    <ifmodule mod_auth_cas.c>
       CASVersion 2
       CASDebug On
       CASValidateServer On
       CASCookiePath /var/tmp/cas/
       CASCertificatePath /etc/pki/tls/certs/globalsignchain.crt
       CASLoginURL https://cas.uwaterloo.ca/cas/login
       CASValidateURL https://cas.uwaterloo.ca/cas/serviceValidate
    </ifmodule>
    
    
  5. Install this file into the appropriate location (on RHEL5 we use /etc/httpd/conf.d) and restart the web server. To use mod_auth_cas, add the following to a .htaccess file, or !VirtualHost container:
    AuthType CAS
    require valid-user

A recent copy of the installation and usage instructions for mod_auth_cas can be retrieved from https://source.jasig.org/cas-clients/mod_auth_cas/trunk/README.

Please note that the README contains a number of configuration directives that can be modified to suit your needs. It is important to know how the timeout-related directives work.

Directive: CASTimeout
Default: 7200 (2 hours)
Description: This is the hard limit, in seconds, for a mod_auth_cas session (whether it is idle or not).
When a session has reached this age and a new request is made, the user is redirected to the CASLoginURL to obtain a new service ticket.  When this new ticket is validated, they will be assigned a new mod_auth_cas session.

Directive: CASIdleTimeout
Default: 3600 (1 hour)
Description: This is a limit, in seconds, of how long a mod_auth_cas session can be idle. When a request comes in, if it has been inactive for CASIdleTimeout seconds, the user is redirected to the CASLoginURL to obtain a new service ticket.

For instance, if you logged in to CAS to access service A via mod_auth_cas, then waited 90 minutes and then went to another CAS-protected service B hosted elsewhere, your CAS ticket-granting ticket (TGT) on the CAS server would still be valid, because the 2 hour idle limit on the CAS server would not have been exceeded. If after 3 hours since initially logging in to CAS, you returned to service A, the mod_auth_cas !CASIdleTimeout value would apply, and the mod_auth_cas module would redirect your session to the !CASLoginURL. However, since the CAS server's 2 hour TGT timeout has not been exceeded because you used the TGT with service B, a new service ticket would be generated for service A against the initial TGT that still remains valid.

PHP

phpCAS is the client library used to integrate CAS authentication into your PHP application. Please note that it is preferable to use a server-side CAS client like mod_auth_cas to protect your site at the directory-level, and use the contents of the REMOTE_USER variable to determine who your logged in user is. The mod_auth_cas approach is simpler and lessens the risk of unauthorized users gaining access to your site through phpCAS programming errors.

  1. You can either install the phpCAS client using PEAR:
    $ pear install http://downloads.jasig.org/cas-clients/php/current/CAS-1.1.1.tgz

    or download the client and extract it into the include_path directory used by your PHP installation. You can find this out by running:
    $ php -r 'echo ini_get('include_path'), "\n";'
    .:/usr/share/pear:/usr/share/php
    $ cd /usr/share/php && wget http://downloads.jasig.org/cas-clients/php/current/CAS-1.1.1.tgz && tar zxf CAS-1.1.1.tgz
  • If the server on which you would like to use phpCAS is a IST supported web server, then phpCAS has already installed via the PEAR method.
  • If you are not an administrator on your web server, then please contact him or her, and ask to have phpCAS installed in the manner described above.
  • ​If you get no response, then you'll have to put the phpCAS library somewhere in your own web directory.
  1. You will need to tell PHP how to include the phpCAS library for use in your application. If phpCAS has been installed in a centrally-accessible location, such as /usr/share/pear or /usr/share/php, then add to the top of your php files:
    include_once('CAS.php');
    
    
    If you have installed phpCAS in your own web directory, then add this code to the top of your php files:
    <?php
    $clientLibraryPath = '/path/to/CAS-1.1.1/'; // change to this where the CAS-1.1.1 is actually located
    $oldPath = set_include_path(get_include_path() . PATH_SEPARATOR . $clientLibraryPath);
    // import phpCAS lib
    include_once($oldPath.'CAS.php');
    
    
  2. Now to add the necessary preamble:
    // enable debugging
    phpCAS::setDebug();
    		
    // initialize phpCAS
    phpCAS::client(CAS_VERSION_2_0,'cas.uwaterloo.ca',443,'/cas');
    // use this server version instead if you want to retrieve CAS attributes:
    // phpCAS::client(SAML_VERSION_1_1,'cas.uwaterloo.ca',443,'/cas');
    		
    // we recommend that you fetch the CA certificate appropriate to the UW cas server you are using and reference that
    phpCAS::setCasServerCACert('/etc/pki/tls/certs/globalsignchain.crt');
    // otherwise no SSL validation for the CAS server<
    // phpCAS::setNoCasServerValidation();
    
    
    Now add the following code to force the user to login before they can view the page:
    // force CAS authentication
    phpCAS::forceAuthentication();
    
    
    To create a logout link for the user, add the following code after forcing cas login:
    if (isset($_GET['logout']))
            phpCAS::logout();
    then create a link with a GET variable for user to click on to logout. You can simply append ?logout=true to the current php file, for example: http://www.uwaterloo.ca/index.php?logout=true


    To get the the username of the person that's currently logged in, you can use:
    $username = phpCAS::getUser();
    // $username = fred
    /* See phpCAS::getAttributes() to retrieve:
       Array
       (
          [name] => Fred Astaire
          [dept] => Human Resources
          [username] => fred
          [email] => fred.astaire@uwaterloo.ca
          [phone] => 519-888-4567 x12345
          [office] => GSC 1001
       )
    */

    Repeat the above steps for all .php page you only want logged in users to see. Complete documentation on phpCAS can be found at https://wiki.jasig.org/display/CASC/phpCAS.

Java

The following instructions are courtesy of Andrew Morton. They will help in setting up CAS for a Java web app "mywebapp" deployed on a Linux server (Ubuntu 9.10 server) with Apache 2.x (http server) and Tomcat 6.x (servlet container), but should suffice for other similar configurations.
 

Apache/Tomcat Installation

  1. Install Apache and Tomcat:
    apt-get install apache2 tomcat6
    ​
    
  2. Enable the Apache AJP module:
    sudo a2enmod proxy_ajp
    
    
  3. Edit /etc/apache2/mods-enabled/proxy.conf to be:
    ProxyRequests Off
    <Proxy http://localhost:8009>
        AddDefaultCharset off
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyVia On
    
    
  4. Edit /etc/apache2/httpd.conf to redirect the path /foo to Tomcat:
    <Location /foo>
        ProxyPass ajp://localhost:8009/foo
    </Location>
    
    
  5. Edit /etc/tomcat6/server.xml by uncommenting this line:
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" >
    
    
  6. Restart Tomcat and Apache:
    sudo /etc/init.d/tomcat6 restart
    sudo /etc/init.d/apache2 restart
    
    
  7. To deploy apps to tomcat, edit /etc/tomcat6/tomcat-users.xml and add a user with role="manager" and use the browser interface at http://YOUR_SITE.uwaterloo.ca:8080/manager/html.
     

Enable HTTPS and Traffic Forwarding

  1. If your server does not already have a SSL certificate, request a UW/IST certificate (since IST is not a recongized certificate authority, browsers will have to add an exception for the certificate) from ist-ca@uwaterloo.ca.
  2. Put the certificate in /etc/ssl/certs and the private key in /etc/ssl/private.
  3. Enable the following Apache modules:
    sudo a2enmod ssl
    sudo a2ensite default-ssl
    ​
    
  4. Edit these 2 lines from /etc/apache2/sites-available/default-ssl as shown:
    SSLCertificateFile /etc/ssl/certs/YOUR_SITE.uwaterloo.ca.crt
    SSLCertificateKeyFile /etc/ssl/private/YOUR_SITE.uwaterloo.ca.key
    
    
  5. Restart Apache:
    sudo /etc/init.d/apache2 restart
    
    
  6. To redirect all http traffic to https, enable the mod_rewrite Apache module:
    sudo a2enmod rewrite
    
    
  7. Add the following near the bottom of /etc/apache2/sites-available/default (VirtualHost *:80:
    RewriteEngine on
    RewriteCond  %{HTTPS}  ^off$
    RewriteRule  ^/foo/?(.*) https://YOUR_SITE.uwaterloo.ca/foo/$1 [L,R]
    
    
  8. Restart Apache:
    sudo /etc/init.d/apache2 restart
    
    
  9. Allow a connection to the CAS server for authentication in the Tomcat !SecurityManager; add this to /etc/tomcat6/policy.d/04webapps.policy:
    grant codeBase "file:/var/lib/tomcat6/webapps/mywebapp/-" {
    permission java.net.SocketPermission "cas.uwaterloo.ca:443",
          "connect,resolve";
           permission java.io.FilePermission "/var/lib/tomcat6/logs", "read";
    };
    
    
  10. Restart Tomcat:
    sudo /etc/init.d/tomcat6 restart
    
    
  11. Configure the java cacerts keystore to use the cas.uwaterloo.ca SSL certificate:
     
    1. Get the cas.uwaterloo.ca certificate:
      echo | openssl s_client -connect cas.uwaterloo.ca:443 2>/dev/null | openssl x509 > tmp/cas.uwaterloo.ca.crt
      
      
    2. Change to the directory containing the cacerts Java keystore file:
      cd /usr/lib/jvm/java-6-sun/jre/lib/security
      
      
    3. Change the cacerts password from the default of "changeit" to something else:
      sudo keytool -storepasswd -keystore cacerts -storepass changeit
      ​
      

      You will be prompted for a new password. Please choose a strong one!
       

    4. Next, import the cas.uwaterloo.ca.crt into cacerts file:
      sudo keytool -import -file /tmp/cas.uwaterloo.ca.crt -alias cas.uwaterloo.ca -keystore cacerts
  12. Include the latest versions of these libraries in mywebapp/WEB-INF/lib:
    * cas-client-core-3.1.10.jar
    * commons-logging-api-1.1.1.jar (be sure it has "-api" in the name!)

The XML

<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!-- Central Authenication Service Filters-->
<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.uwaterloo.ca/cas/login</param-value>
        </init-param>
        <init-param>
                <param-name>serverName</param-name>
                <param-value>https://myserver.uwaterloo.ca</param-value>
        </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.uwaterloo.ca/cas/</param-value>
        </init-param>
        <init-param>
                <param-name>serverName</param-name>
                <param-value>https://myserver.uwaterloo.ca</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>
<!-- I just filter (secure) the Java app -->
        <url-pattern>/MyServlet/*</url-pattern>
<!-- but you could filter the whole web app
        <url-pattern>/*</url-pattern>
-->
</filter-mapping>
<filter-mapping>
        <filter-name>CAS Authentication Filter</filter-name>
        <url-pattern>/MyServlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>/MyServlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/MyServlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <url-pattern>/MyServlet/*</url-pattern>
</filter-mapping>
        
<listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>ca.uwaterloo.mypackage.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<!-- I use an (unsecured) html login file -->
        <welcome-file>/login.html</welcome-file>
<!-- but it could go straight to MyServlet
        <welcome-file>MyServer</welcome-file>
-->
</welcome-file-list>
</web-app>

The Java

# CAS login will happen automatically and redirect back to the place in
# mywebapp where it was called
# CAS logout is not automatic
# use the following code in your logout routine
# note that (request,response are parameters to
# HttpServlet::doGet and HttpServlet::doPost)

request.getSession(false).invalidate();
response.sendRedirect("https://cas.uwaterloo.ca/cas/logout?service=http://myserver.uwaterloo.ca/mywebapp");

Plone / Zope

Zope (http://zope.org/) is a web application server implemented in Python with an underlying transactional object database. Plone (http://plone.org/) is a CMS/portal application built on Zope. 

Support for CAS is provided in Plone through an addon called collective.castle (http://plone.org/products/collective-castle). To add CAS to a Plone site simply:

  1.  Add 'collective.castle' to the 'eggs' section of your Plone buildout.cfg
  2.  Run buildout
  3.  Restart your Plone instance.
  4.  In _'Site Setup > Add-on Products'_, choose to install _"Collective Castle (UI for CAS)"_
  5. Then, once installed, goto _'Site Setup > CAS Configuration'_ and set:
    CAS Log in URL = https://cas.uwaterloo.ca/cas/login
    CAS Log out URL = https://cas.uwaterloo.ca/cas/logout
    CAS Validate URL = https://cas.uwaterloo.ca/cas/validate
    *NOTE:* Leave defaults elsewhere.

Once this is completed, the default login/logout actions on your Plone site will be replaced with castle_login/castle_logout. This means that every authentication request for content in your site will be sent along to Waterloo's CAS. Through the magic of Plone's PluggableAuthService, any username returned from CAS as succeeding that matches a user in your Plone site will be granted access. Plone's role-based permissions system controls authorization (but defers all authentication requests to CAS).

Django (Python Web Framework)

Django is a distributed web service platform (http://www.djangoproject.com/). In our work, django-cas (http://code.google.com/p/django-cas/) has had no problems interacting with Waterloo's CAS service.

Ruby on Rails (RoR)

Depending on the version of OpenSSL installed on your machine, you may need to set `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version] = 'TLSv1'`. The default 'SSLv23' no longer handshakes successfully as of Jan 21st, 2014.

You may want to try the rubycas-client (http://code.google.com/p/rubycas-client/) to work with Waterloo's CAS service.