Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

...

Table of Contents

...

UH Login (CAS) is available for University of Hawai?i (UH) Web site developers to authenticate users with their UH username and password

Table of Contents
maxLevel3
excludeTable of Contents

Overview

UH Login (CAS) is available for University of Hawaiʻi (UH) Web site developers to authenticate users with their UH username and password. It alleviates the problem of having to develop a user authentication system as part of the Web-enabled application (web application) development. It also provides increased security for users by not allowing Web applications to handle their passwords (often using insecure means such as sending it in the clear or unnecessarily storing it).

...

In addition to authentication services (AuthN), UH Login (CAS) may also provide other information (attributes) about the authenticated subject. These attributes are released using the the SAML 1.1 protocol. A registered Web application may obtain attributes about the user to implement access control (authorization) decisions, beyond the simple determination that the user has successfully authenticated with their password. For example, if an application is designed to be accessible only to faculty, that app can compare the eduPersonAffiliation attribute to determine if the user is faculty. If you do not perform any access control then anyone in the UH Core LDAP Directory Service will be able to use your Web application. This includes all current people in the UH System as well as visitors allowed by the Visitor Internet Access (VIA).

...

Info
titleThe UH Web Login Service is provided via Apereo's Central Authentication Service (CAS).

Currently UH Login is running CAS version 56.03.105.

Please refer to Apereo documentation for authoritative references for CAS client integration and the CAS protocol. The CAS Community mailing list and archives are also valuable sources of information and support.

Additional  info

This information was derived from Apereo's :

, Apereo's , and .

...

Before You Register Your Application URL …

Before you register your application URL there are a few details to first consider:

  1. Will authentication include the release of attributes to your application?
    1. If yes, UH Data Governance guidelines apply.  For each unique application you must submit a separate request.  What that means is that you cannot register a single URL and host multiple applications under it.  
  2. Is your application hosted on a non-UH server?
    1. If yes, your request may be subject to the UH Data Sharing Request process. Please send an inquiry to datagov@hawaii.edu or call (808) 956-7487.

...

Register Your Application URL

For security purposes, application URLs must be registered in order to prevent unauthorized use.

...

Web Login process

Web applications registered for UH Login use a link or redirect from their main page to the secure HTML CAS form.

To Authenticate Users

  • A user enters their UH username and password on the UH Login page.
  • After submission, the Web Login Service redirects the user back to your web application along with a service ticket provided by the Web Login Service.
  • Your web application then requests that UH Login validate this ticket.
    • If the user supplied the correct authentication credentials (username/password), UH Login will return a success response to your web application.
    • Otherwise, a failure response is returned.

...

Note
titleCAUTION

After UH Login redirects the user back to your app and you have validated the service ticket, redirect the user to an URL that does not include the service ticket. This reduces the risk of the user bookmarking a URL containing a service ticket. A bookmarked URL containing a service ticket is a problem because the CAS software isn't on guard for this and it results in a looping problem that sends the user back and forth between your application and UH Login, or it may immediately return an unsuccessful authentication result despite the user having provided the correct user password.

...

Conventions & Definitions

  • "Client" refers to the end user and/or the web browser.
  • "Server" refers to UH Login (CAS).
  • "Service" refers to the application the client is trying to access (i.e., your application).
    • "TARGET" for samlValidate
  • <LF> is a bare line feed (ASCII value 0x0a).

...

CAS URIs

URIs for CAS use the hostname followed by /cas and ended with the desired service. In the examples that follow, substitute the following for $WEBLOGIN-HOST for the appropriate environment.

  • Production
    • https://authn.hawaii.edu/
  • Test
    • https://cas-test.its.hawaii.edu/ (testing does not require registration of your URL)
  • Future Test
    • https://cas-future-test.its.hawaii.edu/
  • Deprecated Production
    • cas-deprecated.its.hawaii.edu


Info
titleTest vs. Production, what's the difference?

The primary difference between the Test and Production environments is the source of credentials used for authentication and attributes. The production Web Login instance uses production LDAP, whereas the test Web Login instance uses our test LDAP instance. Data in the test LDAP instance generally represents a (somewhat stale) snapshot of the production LDAP. Developers should verify that the credentials they wish to test are available in test LDAP.

The login page presented to the user in the test environment is also conspicuously identified as being "Not intended for normal use" and a "test-env" and for "Testing Only".

Append the following as needed:

...

Info
titleCAS clients

Note that CAS clients are available that handle many of the login and ticket validation details for you. If your development can make use of one of the available CAS clients (eg, Java, PHP) you will probably want to take advantage of them rather than trying to reinvent the wheel.

...

Log in Securely

...

/login

To have a user login securely put a link on your main page to the "login securely" URL with a request parameter named service and having a value that is the Service URL (i.e., the URL of the main page or a page that will be able to handle an HTTP request with a parameter). This link should be labeled with something like "Login Securely" to establish in your user's mind that the password will not be seen by your application and is handled securely. See the next section on ticket validation for information about how your application finds out the username.

...

  • service
    • used for AuthN responses
    • validate service ticket with
      • cas/validate
      • cas/serviceValidate
      • cas/samlValidate
  • renew (OPTIONAL)
    • if this parameter is set, single sign-on will be bypassed. In this case, CAS will require the client to present credentials regardless of the existence of a single sign-on session with CAS.
  • other parameters are described on the CAS Protocol wiki page

The service parameter should be set to the URL that the Web Login service will redirect the client to after successful authentication, as well as where the Web Login service will direct success/failure responses.

...

Info
titleNotes
  1. The service/target URL must be a real URL. For example, most Web servers have a default page that is returned when you request a URL that ends with a forward slash character, "/". This often results in redirects to index.html, index.htm, or index.jsp while others may use default.htm, default.asp, or something similar.
  2. Since the Service URL is passed as the value of a query parameter, it should be URL-escaped to ensure proper interpretation by UH Login. Please refer to Section 2 and Appendix A of RFC 3986 for details.

...

Ticket Validation (

...

CAS protocol 1.0

...

, AuthN, simple text response)

/validate

This section describes how your Web application finds out the username of a user that has successfully logged in.

...

  • Here's an example of the URL used by UH Login to redirect the request back to the Web site (with a sample ticket):

    No Format
    https://myserver/myapp?ticket=ST-3-8tkkJbPThesE1cZjVVtc
    


  • The server-side processing of your Service URL must validate the extracted authentication token by sending an HTTP GET request with the following parameters:

    No Format
    service=<Service URL>
    ticket=<service ticket>


  • Using your URL with ticket, send your request to UH Login:

    No Format
    https://$WEBLOGIN-HOST/cas/validate?service=https://myserver/myapp&ticket=ST-95-a1kjb6g4Tcdeh17vfy6g
    


    Info

    Append &renew=true to disallow SSO.


  • After validating the service ticket, UH Login will return a text document indicating success or failure.

    Code Block
    xml
    xml
    titleOn ticket validation success:
    yes<LF>
    username<LF>
    


    Code Block
    xml
    xml
    titleOn ticket validation failure:
    no<LF>
    <LF>
    

...


...

Ticket Validation (

...

CAS protocol 2.0, AuthN, XML response)

...

/serviceValidate

This section describes how your Web application finds out the username of a user that has successfully logged in.

...

  • Here's an example of the URL used by UH Login to redirect the request back to the Web site (with a sample ticket):

    No Format
    https://myserver.example.edu/myapp?ticket=ST-7655-K6dyN9ystYwdOZynSnak-cas


  • The server-side processing of your Service URL must validate the extracted authentication token by sending an HTTP GET request with the following parameters:

    No Format
    service=<Service URL>
    ticket=<service ticket>
    


  • Using your URL with ticket, send your request to UH Login:

    No Format
    https://$WEBLOGIN-HOST/cas/serviceValidate?service=https://myserver.example.edu/myapp&ticket=ST-7655-K6dyN9ystYwdOZynSnak-cas


    Info

    Append &renew=true to disallow SSO.


  • After validating the service ticket, UH Login will return an XML-fragment indicating success or failure.

    Code Block
    xml
    xml
    titleOn ticket validation success:
    <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
        <cas:authenticationSuccess>
            <cas:user>joebogus</cas:user>
            </cas:authenticationSuccess>
    </cas:serviceResponse> 


    Code Block
    xml
    xml
    titleOn ticket validation failure:
    <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
        <cas:authenticationFailure code="INVALID_TICKET">
            Ticket ST-7655-K6dyN9ysFOOdOZynSnak-cas not recognized
        </cas:authenticationFailure>
    </cas:serviceResponse>


    Info
    titleError codes

    The following values may be used as the "code" attribute of authentication failure responses.

    • INVALID_REQUEST
      • not all of the required request parameters were present
    • INVALID_TICKET
      • the ticket provided was not valid, or the ticket did not come from an initial login and "renew" was set on validation. The body of the <cas:authenticationFailure> block of the XML response SHOULD describe the exact details.
    • INVALID_SERVICE
      • the ticket provided was valid, but the service specified did not match the service associated with the ticket. CAS MUST invalidate the ticket and disallow future validation of that same ticket.
    • INTERNAL_ERROR
      • an internal error occurred during ticket validation

...

...


...

Ticket Validation (

...

CAS protocol 3.0, AuthN with attributes, SAML response):

/samlValidate

This section describes how your Web application determines the username and possibly additional attributes for a user that has successfully logged in.

...

Note
titleFERPA laws may apply!

Information about students must be handled carefully and in accordance with University of Hawai?i data governance policies. FERPA laws constrain what may be published about students. Please check with your Admissions and Records Office for details.

...

Logging Out (SLO)

...

/logout

Web applications that login a user must handle their own session state and should offer the user the ability to log out of their session. Without the logout service provided by CAS, a user returning to the web application's Service URL, will be automatically logged back in because of the ticket-granting cookie also provided by CAS stored by the client. This is a single sign-on feature across web applications that use UH Login. There are two basic ways to "log out"; logout from application and UH Login single sign-on or logout from application and force re-authentication to UH Login.

...

Note
titleCAS /logout will affect applications other than your own!

Note that use of /logout may affect any other application that is also using the CAS Single Sign-On (SSO) session. Other applications may share the same CAS SSO session that is terminated by the use of /logout, and their SSO session will likewise be terminated as well when the ticket granting cookie is destroyed.

Please refer to the CAS reference documentation for a more extensive discussion of this issue.

Parameters
  • service (OPTIONAL)
    • the identifier of the service to redirect to after logging out
    • the service parameter must be also be a registered service URL
  • url (DISABLED)

    Note

    Although Aperero's CAS protocol documentation describes the use the the url parameter, the Aperero developers have disabled it in recent versions of CAS to prevent potential abuse. Their explanation of the situation may be found in this thread from the cas-users mailing list. The url parameter defined in the former CAS 2.0 specification is not a valid parameter in CAS 3.0 anymore. CAS Servers MUST ignore given url parameters.


Examples
  • To logout a user and prevent her from automatically logging back into a Web application, the Web application can forward the user to the Logout URL of UH Login. That URL will destroy the ticket-granting cookie that enables the single sign-on feature and gives the user a page that informs them that they have logged out of UH Login.

    No Format
    https://$WEBLOGIN-HOST/cas/logout
    


  • To logout a user and prevent her from automatically logging back into a Web application, the Web application can forward the user to the Logout URL of UH Login. That URL will destroy the ticket-granting cookie that enables the single sign-on feature and redirect the user to the URL identified by the service parameter.

    No Format
    https://$WEBLOGIN-HOST/cas/logout?service=https://myserver/myapp
    


    Info

    The URL provided by the service parameter must be registered to use UH Login.

...


...

Note

...

titleSLO is not enabled
Because SLO may affect other applications using SSO[*], it has been disabled as of the implementation of CAS 6.3.5.

[*] From the CAS documentation for Single Logout (SLO):

When a CAS session ends, it notifies each of the services that the SSO session is no longer valid, and that relying parties need to invalidate their own session. Remember that the callback submitted to each CAS-protected application is a notification; nothing more. It is theresponsibility of the applicationto intercept that notification and properly destroy the user authentication session, either manually, via a specific endpoint or more commonly via a CAS client library that supports SLO.

Also note that since SLO is a global event, all applications that have an authentication record with CAS will by default be contacted, and this may disrupt user experience negatively if those applications are individually distinct from each other. As an example, if user has logged into a portal application and an email application, logging out of one through SLO will also destroy the user session in the other which could mean data loss if the application is not carefully managing its session and user activity.


Access Control

It is every developer's responsibility to perform any necessary access control (authorization, AuthZ) after a user has logged on to their Web site. This is may be done by using information as attributes for the user. The affiliation, campus, or campus affiliation data should be enough to filter out unauthorized users. Alternatively, you choose explicitly may allow or disallow by username. Ultimately, it is up to each developer to determine how to implement access controls based on available information.

...

Sample Clients

...

...

Java client

Aperero provides a an example of SAML 1.1 Ticket Validation Filter.

...

Note

Apereo has taken over CAS from JASIG. The current version of the CAS client may be found here:

To use this client, as with the SAML 1.1 Ticket Validation Filter above, you may need the following jar files:

  • cas-client-core
  • cas-client-support-saml
  • commons-codec
  • commons-logging
  • joda-time
  • log4j
  • opensaml
  • slf4j-api
  • xmlsec

...

...

UH CAS Demo in Java

UH ITS' own Frank Duckart wrote the following CAS demo using Java and Servlets:

...

Probably not a great idea, but it is also possible to create a CAS client login using JSP only:
Project Repo:  https://github.com/fduckart/uh-jsp-casdemo

...

phpCAS client

The phpCAS module is a PHP library that interacts with CAS and allows you to work with user and authentication objects. It also allows for attribute release. You can download and extract the latest phpCAS version from http://downloads.jasig.org/cas-clients/php/current.tgzThe latest phpCAS version may be obtained from the phpCAS Github page. Documentation for phpCAS can be found here.

It is recommended after you extract the release that you create a symlink in the directory to the CAS folder. For example, if your phpCAS release is located in /usr/lib/php/CAS-1.3.1, you would create the symlink in /usr/lib/php. This allows you to have multiple versions of phpCAS without the need to continually overwrite folders.

...

Expand
titleClick to expand: config.php for phpCAS-1.6.0


Code Block
titleconfig.php
<?php

/**
 * The purpose of this central config file is configuring all examples
 * in one place with minimal work for your working environment
 * Just configure all the items in this config according to your environment
 * and rename the file to config.php
 *
 * PHP Version 57
 *
 * @file     config.php
 * @category Authentication
 * @package  PhpCAS
 * @author   Joachim Fritschi <jfritschi@freenet.de>
 * @author   Adam Franco <afranco@middlebury.edu>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
 * @link     https://wiki.jasig.org/display/CASC/phpCAS
 */

$phpcas_path = '/usr/lib/php/CAS-1.3.1/CAS../../source/';

///////////////////////////////////////
// Basic Config of the phpCAS client //
///////////////////////////////////////

// Full Hostname of your CAS Server
$cas_host = '$WEBLOGIN-HOSTcas.example.com';

// Context of the CAS Server.
// The phpCAS client will use this as the root directory for the CAS server and
// append the required page calls.
$cas_context = '/cas';

// Port of your CAS server. Normally for a https server it's 443
$cas_port = 443;

// Path to the ca chain that issued the cas server certificate (see above)
// If you are unable to set this path, you will not be able to use the
// phpCAS::setCasServerCACert($cas_server_ca_cert_path) methodport = 443;

// Path to the ca chain that issued the cas server certificate
$cas_server_ca_cert_path = '/path/to/cachain.pem';

//////////////////////////////////////////
// Advanced Config for special purposes //
//////////////////////////////////////////

// The "real" hosts of clustered cas server that send SAML logout messages
// Assumes the cas server is load balanced across multiple hosts
$cas_real_hosts = array('$WEBLOGIN-HOST')////////

// The "real" hosts of clustered cas server that send SAML logout messages
// Assumes the cas server is load balanced across multiple hosts
$cas_real_hosts = array('cas-real-1.example.com', 'cas-real-2.example.com');

// Client config for the required domain name, should be protocol, hostname and port
$client_service_name = 'http://127.0.0.1';

// Client config for cookie hardening
$client_domain = '127.0.0.1';
$client_path = 'phpcas';
$client_secure = true;
$client_httpOnly = true;
$client_lifetime = 0;

// Database config for PGT Storage, ifPGT used.Storage
$db = 'pgsql:host=localhost;dbname=phpcas';
//$db = 'mysql:host=localhost;dbname=phpcas';
$db_user = 'phpcasuser';
$db_password = 'mysupersecretpass';
$db_table = 'phpcastabel';
$driver_options = '';

///////////////////////////////////////////
// End Configuration -- Don't edit below //
///////////////////////////////////////////

// Generating the URLS for the local cas example services for proxy testing
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $curbase = 'https://' . $_SERVER['SERVER_NAME'];
} else {
    $curbase = 'http://' . $_SERVER['SERVER_NAME'];
}
if ($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
    $curbase .= ':' . $_SERVER['SERVER_PORT'];
}

$curdir = dirname($_SERVER['REQUEST_URI']) . "/";

// CAS client nodes for rebroadcasting pgtIou/pgtId and logoutRequest
$rebroadcast_node_1 = 'http://cas-client-1.example.com';
$rebroadcast_node_2 = 'http://cas-client-2.example.com';

// access to a single service
$serviceUrl = $curbase . $curdir . 'example_service.php';
// access to a second service
$serviceUrl2 = $curbase . $curdir . 'example_service_that_proxies.php';

$pgtBase = preg_quote(preg_replace('/^http:/', 'https:', $curbase . $curdir), '/');
$pgtUrlRegexp = '/^' . $pgtBase . '.*$/';

$cas_url = 'https://' . $cas_host;
if ($cas_port != '443') {
    $cas_url = $cas_url . ':' . $cas_port;
}
$cas_url = $cas_url . $cas_context;

// Set the session-name to be unique to the current script so that the client script
// doesn't share its session with a proxied script.
// This is just useful when running the example code, but not normally.
session_name(
    'session_for:-'
    . preg_replace('/[^a-z0-9-]/i', '_', basename($_SERVER['SCRIPT_NAME']))
);
// Set an UTF-8 encoding header for internation characters (User attributes)
header('Content-Type: text/html; charset=utf-8');
?>


...

Expand
titleClick to expand: Sample PHP code to authenticate and retrieve attributes


// // phpCAS simple client //
Code Block
titlephpcas-test.php
phpcas-test.php
<?php

/**
 * Advanced example for SAML with attributes and single logout
 *
 * PHP Version 7
 *
 * @file     example_advanced_saml11.php
 * @category Authentication
 * @package  PhpCAS
 * @author   Joachim Fritschi <jfritschi@freenet.de>
 * @author   Adam Franco <afranco@middlebury.edu>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
 * @link     https://wiki.jasig.org/display/CASC/phpCAS
 */

// Load the settings from the central config file
require_once 'Configconfig.php';

// Load importthe phpCASCAS lib
require_once $phpcas_path . '/CAS.php';

// This file will capture debugging output, useful to see what your client is doing.
// Make sure your application has read/write permissions.
Enable debugging
phpCAS::setDebug( "/filepath/to/your/log/file" );

// initialize phpCASsetLogger();
// Enable Ifverbose youerror aremessages. interestedDisable in the return of user attributes, use the followingproduction!
phpCAS::setVerbose(true);

// Initialize parameterphpCAS
phpCAS::client( SAML_VERSION_1_1, $cas_host, $cas_port, $cas_context, $client_service_name);

// However, if you are only interested in user authentication, you can use
// the following:
// phpCAS::client( CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context, $client_service_name);

// For production use set the CA certificate that is the issuer of the cert
// on the CAS server and uncomment the line below.  Otherwise comment out this
// line and uncomment the phpCAS::setNoCasServerValidation() one
// Note, however, that if your App does not reside on the same server as CAS, the cert
// youon maythe runCAS intoserver problemsand determininguncomment the pathline to the certificate.
// below
phpCAS::setCasServerCACert($cas_server_ca_cert_path);

// For quick testing you can disable SSL validation of the CAS server.
// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
// phpCAS::setNoCasServerValidation();

// Handle SAML logout requests that emanate from the CAS host exclusively.
// Failure to restrict SAML logout requests to authorized hosts could
// allow denial of service attacks where at the least the server is
// tied up parsing bogus XML messages.
phpCAS::handleLogoutRequests(true, $cas_real_hosts);

// Force CAS authentication on any page that includes this file
phpCAS::forceAuthentication();

// Renew CAS authentication with renew=true on any page that includes this file
// logout if desired
Use this in place of phpCAS::forceAuthentication();
// phpCAS::renewAuthentication();

// Some small code triggered by the logout button
if (isset($_REQUEST['logout'])) {
    phpCAS::logout();
}

?>

<html>
  <head>
    <title>phpCAS simple client< client with user attributes</title>
  </head>
  <body>

    Authentication succeeded for user
    <strong><?php echo phpCAS::getUser(); ?></strong>.

    <h3>User Attributes</h3>
    <ul>
    <?php
    foreach ( phpCAS::getAttributes() as $key => $value )
    {
        if ( is_array( $value ) )
        {
            echo '<li>', $key, ':<ol>';
            foreach ( $value as $item )
            {
                echo '<li><strong>', $item, '</strong></li>';
            }
            echo '</ol></li>';
        }
        else
        {
            echo '<li>', $key, ': <strong>', $value, '</strong></li>';
        }
    }
    ?>
    </ul>

    <p><a href="?logout=">Logout</a></p>g
  </body>
</html>


Theoretical examples of using CAS authentication across multiple pages, combined with using custom session variables.

Expand
titleClick to expand: Example PHP code to retain CAS3 CAS authentication across multiple pages

To use CAS across multiple pages, there are two ways to go about it:

The first is to include your phpcas-test.php file at the top of each page. This serves to activate the phpCAS client and will determine if the user has authenticated or not. You can modify your phpcas-test.php file by first checking phpCAS::isAuthenticated() which returns a boolean true or false; if false you can forceAuthentication().

The second is if you intend to use custom session variables across your pages. phpCAS has its own session management values that may interfere with whatever you're doing, so the solution I came up with was storing those CAS values into my app's session variables.

Please note that all examples provided here are extremely condensed, as I am only attempting to demonstrate how one can retain CAS session values along with app-specific session values. As such they should be treated more like pseudocode or an algorithm.

Code Block
titleindex.php
==========================================
index.php (summarized)
This page authenticates the user to my application.  Here I check if the user
is authenticated, and if so, I capture the CAS3CAS session values and user
attributes.
==========================================
<?php

include_once( "../../lib/cas3cas.class.inc.php" )  
// This file is similar to the phpcas-test.php example
// The inclusion of this file activates the phpCAS client, and can
// trigger the authentication of the user if they're not logged in.
// My cas3cas.class.inc.php file is below this example.

// Display session values, to double-check what we have
// The value of $DEBUG is set in my app's configuration file.
// You will notice that the session id and name are set by CAS3.
if ( $DEBUG ) {
    if ( isset( $_SESSION ) ) {
        print "<p />SESSION values set<br />";
        print "Session ID: " . session_id() . "<br />";
        print "Session Name: " . session_name(). "<br />";
        print_r( $_SESSION );
        print "<p />";
    }
}

// Save the attributes
$cas_attributes = array();
foreach ( phpCAS::getAttributes() as $key => $value ) {
    $cas_attributes[$key] = $value;
    $DEBUG && print "phpCAS attribute: $key, Value: $value<br />";
}

// Save the token
$cas_token = session_id();

<!-- HTML form to log user into my application.  I've cut out elements like -->
<!-- the text fields  for username and password entry to focus on CAS3 session -->
<!-- Here, I am submitting the user attributes as hidden fields to the -->
<!-- next page that does the app authentication -->
<form action="app_authentication.php" name="logging_in" method="POST">
    <input type="hidden" name="state" value="cas3cas_authenticated" />
    <?php
    foreach ( $cas_attributes as $name => $attribute ) {
        if ( ! is_array($attribute) ) {
            print '<input type="hidden" name="cas_attributes['.$name.']" value="'.$attribute.'" />';
        }
        else {
            // Some CAS3CAS user attributes are multi-valued.
            foreach ( attribute as $sub_name => $sub_attr ) {
                print '<input type="hidden" name="cas_attributes['.$name.']['.$sub_name.']" value="'.$sub_attr.'" />';
            }
        }
    }
    ?>
    <input type="hidden" name="cas_token" value="<?php print $cas_token; ?>" />
</form>
?>


Code Block
titlecas3cas.class.inc.php
==========================================
cas3cas.class.inc.php
simplified version
==========================================
<?php
require_once "PHPCAS_CONFIG.php";       // this is my config file
require_once $phpcas_path . "CAS.php";  // import phpCAS

phpCAS::setDebug( "/filepath/to/where/i/store/app/logs/cas_debug.log" );
phpCAS::client( SAML_VERSION_1_1, $cas_host, $cas_port, $cas_context, $client_service_name );
phpCAS::setCasServerCACert( $cas_server_ca_cert_path );
phpCAS::handleLogoutRequests( TRUE, $cas_real_hosts );

// If the user isn't authenticated, force authentication
// Here is where we determine if a user has logged in via CAS3CAS
if ( ! phpCAS::isAuthenticated() ) {
    phpCAS::forceAuthentication();
}

if ( isset( $_GET['logout'] ) ) {
    phpCAS::logout();
}
?>


Code Block
titleapp_authentication.php
==========================================
app_authentication.php
This page just handles authenticating my application, as users have passwords
that are not the same as their UH account passwords.
==========================================
<?php

// IMPORTANT!
// Note that I do not include cas3cas.class.inc.php in this page!  If I did,
// phpCAS removes my app's session in order to use its own, and I end up losing
// the user-submitted form in the same process.

// Check if we have the POSTed "state" value of "cas3cas_authenticated" from index.php
if ( (! isset( $_POST['state']) ) || ($_POST['state'] != 'cas3cas_authenticated') ) {
    header( "Location: index.php?error=unauthenticated" );
    exit();
}

// Grab the username, app password, and CAS values
$entered_username   = $_POST[ 'username' ];
$entered_password   = $_POST[ 'password' ];
$cas_attributes     = $_POST[ 'cas_attributes' ];
$cas_token          = $_POST[ 'cas_token' ];

// Start a new session (non CAS session)
session_name( $PHP_SESS_ID );  // This is set in my app's config file so I can reuse and recall anywhere
if ( ! session_start() ) {
    die( "Could not start non-CAS session!" );
}

// Debugging statements, to ensure the values and constants are what I expect them to be.
// Note here that the session id and name should be values that I just set.
$DEBUG && print "
    <p />
    Session Name: ".session_name()."<br />
    Session ID: ".session_id()."<br />
    APP HOST: $APP_HOST<br />
    LDAP: $LDAP_HOST<br />
    Location: ".$_SERVER['PHP_SELF']."
    <p />
";

// Assume I have code to validate the user's name and password.
// Next I store the CAS attributes and token into my currently-active session ($PHP_SESS_ID)
if ( $user_validated ) {
    $_SESSION[ $CAS_ATTRIBUTES  ] = $cas_attributes;
    $_SESSION[ $CAS_TOKEN       ] = $cas_token;
}
?>


Code Block
titleother_pages.php
==========================================
all other pages in my application
Now that I have stored the CAS3CAS token and attributes, I can access them
in the rest of my application.
==========================================
<?php

// I still do not include the cas3cas.class.inc.php page

# Start a new session (non CAS session)
session_name( $PHPSESSID );
if ( (! isset( $_SESSION)) || (! $_SESSION) ) {
    if ( ! session_start() ) {
        die( "Cannot start non-CAS session!");
    }
}

// Here I check that the user has a CAS3CAS token (which was set in app_authentication.php)
if ( (! isset( $_SESSION[$CAS_TOKEN] )) || ($_SESSION[$CAS_TOKEN] == $EMPTY_STR) ) {
    $file->write_log_file( "Unauthenticated access to ".$_SERVER['PHP_SELF'], $LOG_DIR.$LOG_WEBLOG );
    header( "Location: index.php?error=unauthenticated" ); // index.php has an error-handler.
    exit();
}

$cas_attributes         = $_SESSION[ $CAS_ATTRIBUTES ];
$uh_username            = $cas_attributes[ $UID ];
$uh_number              = $cas_attributes[ $UHUUID ];

// session id and name should still be the values I set, not CAS3CAS's values.
// You could also include the CAS3CAS values in this debug statement if you
// wanted to verify retention and accuracy.
$DEBUG && print "
    <p />
    Session Name: ".session_name()."<br />
    Session ID: ".session_id()."<br />
    APP HOST: $APP_HOST<br />
    LDAP: $LDAP_HOST<br />
    USER: $uh_username<br />
    UHUUID: $uh_number<br />
    Location: ".$_SERVER['PHP_SELF']."
    <p />
";
?>


...

No Format
Array ( [0] => yes [1] => jschmidt [2] => )

...

cURL client (no attributes requested)

Below is a PHP script using cURL to establish a connection with the CAS server.

...

Expand
titleClick to expand: cas_test.php


Code Block
<?php
# Test CAS URLs
$CAS_LOGIN_URI      = "https://$WEBLOGIN-HOST/cas/login";
$CAS_VALIDATE_URI   = "https://$WEBLOGIN-HOST/cas/validate";
$CAS_LOGOUT_URI     = "https://$WEBLOGIN-HOST/cas/logout";

$single_signon = TRUE;

# Here is where we check if the user has authenticated.  If we cannot find a ticket,
# redirect the user to the CAS login page.
if ( ! isset($_GET["ticket"]) )
{
    $location = "Location: ".$CAS_LOGIN_URI."?service=".urlencode($_SERVER["SCRIPT_URI"]);

    # If we haven't enabled single sign-on, the user has to renew each time.
    if ( ! $single_signon )
    {
        $location = $location."&renew=true";
    }

    header($location);
    exit();
}
else
{
    # Initialize our CURL session with the CAS validation URL.  Supply the server script and ticket.
    $validate_string    = $CAS_VALIDATE_URI."?service=".urlencode($_SERVER["SCRIPT_URI"])."&ticket=".$_GET["ticket"];

    $ch = curl_init($validate_string);

    # set the option to return the results
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    $cas_return = explode("\n", curl_exec($ch));

    # This dumps out the return values from our cURL request.  Later we check whether or not the user successfully authenticated.
    echo "CAS return via cURL: ";
    print_r($cas_return);
    echo "<br />";

    if ( $cas_return[0] == "yes" )
    {
        echo "User successfully authenticated via CAS<br />";
        for ( $i=0; $i<count($cas_return); $i++ )
        {
            echo "Cas Return #$i: ".$cas_return[$i]."<br />";
        }
    }
    else
    {
        echo "User not validated<br />";
    }
}

?>

...


...

Spring Security CAS Authentication

...

...

...

Frequently Asked Questions (FAQ)

Why does my site automatically login a returning user after they logout of their session with my site?

...

A future enhancement could make single sign-on an option for the user so the default will be no single sign-on. If the user chooses to enable single sign-on when authenticating to UH Login, only those apps that don't use the renew parameter will permit single sign-on if the user doesn't logout via the Logout URL from a previously visited appLogout URL from a previously visited app.

Why can't I login successfully to the CAS test environment?

There are several reasons for this and one or both may be applicable:

  1. Currently you need to use a UH VPN to access CAS test.  (not a requirement for production CAS, nor will it ever be)
  2. CAS test points to a test LDAP instance that may not have your current password.  Send an email to the IAM team to request a "password sync" if needed.

Can anyone use my Web site?

...

Since this feature is not compatible with our existing business rules, IAM will be disabling this feature during the 2014 calendar year.

...

...

Troubleshooting

Info
Often the best place to start if you encounter errors, is a review of your logs for indications as to the nature of the problem. This will often yield productive keywords or strings that may be useful in a search or requests for technical support.

The following issues have been encountered by some of our developers.

Application

...

Not Authorized to Use UH Login

Problem:

Your application cannot successfully authentication against CAS.

Example error message:

Expand
Panel

The application you attempted to authenticate to is not authorized to use UH Login.


Solutions:

Expand


Panel
  • If you have requested attributes, make sure you are using https.
  • Check that the URL matches the URL specified in your original CAS URL registration request.
    • Common errors
      • Adding or leaving out "www" not in registered registered URL
      • Using "http" as the protocol rather than "https"


...

SSLv3 is being deprecated as a weak encryption protocol. As it is disabled on servers, clients that attempt to use SSLv3 for their connections will fail to do so.

Example error messages:

...

...

Java:

...

expand
Panel

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

title

PHP, Python:

...

Panel

error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure


Solutions:

Configure applications to use TLS instead of SSL for encrypted connections. Current versions of SSL/TLS (e.g. OpenSSL, Java) libraries disable SSLv3 by default. However if you are using an older version, you may need to explicitly disable SSLv3 and use TLS instead.

...

Expand
titlePHP: Click here to expand...

PHP developers may need the following (or equivalent):

Panel

curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');

Reference: PHP curl_setopt documentation

Note

Until we also expand the available ciphers CURLOPT_SSL_CIPHER_LIST may need to be adjusted as well. Currently only SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA ciphers are enabled.

The PHP reference above suggests "RC4-SHA and TLSv1 are valid cipher lists". If "TLSv1" works for you, that's probably what you want and it should be forward compatible. We have also seen references that suggest that PHP can accept OpenSSL format cipher lists, but this has not been verified.

This page

seems to be a decent overview of using TLS with PHP.

This page also seems to be a decent overview of using TLS with PHP: Insufficient Transport Layer Security (HTTPS, TLS and SSL)

...

No Format
2009-08-13 16:30:58,313 DEBUG [org.jasig.cas.client.validation.Saml11TicketValidator] - <skipping assertion that's not yet valid...>
2009-08-13 16:30:58,316 WARN [org.jasig.cas.client.validation.Saml11TicketValidationFilter] - <org.jasig.cas.client.validation.TicketValidationException: No valid assertions from the SAML response found.>
org.jasig.cas.client.validation.TicketValidationException: No valid assertions from the SAML response found. 

Solutions:

Expand
  • Our CAS servers have their time synchronized via the NTP protocol. Client systems that also use NTP are presumably unlikely to encounter this problem.
    • (info) This should be the preferred approach.
  • The Java client has a tolerance init parameter to specify the a timing tolerance in ms:

    Code Block
    xml
    xml
    <init-param>
     <param-name>tolerance</param-name>
     <param-value>60000</param-value>
    </init-param>
    
  • The DotNetCasClient 3rd party plugin for .NET projects has an attribute to specify ticket timing tolerance in ms:

    Code Block
    ticketTimeTolerance="30000"

...


Reference: CAS Users mailing list thread on time synchronization


Reference: CAS Users mailing list thread on time synchronization

...

...

Technical Support

There is an active UH community of developers and a good chance that at least one of them has experience with your scenario.  It is well worth joining this community's email list if you've not already done so.  For details, visit App Developers Forum page.  Note that the ITS Identity and Access Management team also participates on this list.