CAS Client Plugin

  • Tags : security, cas
  • Latest : 1.0
  • Last Updated: 31 December 2009
  • Grails version : 1.*
  • Authors : C W
0 vote
Dependency :
compile ":cas-client-plugin:1.0"

Documentation

Summary

Installation

grails install-plugin cas-client

Description

JA-SIG CAS Client Plugin for Grails

Introduction

This plugin provides a simple way of enabling JA-SIG CAS client integration.

Current release version is 1.2 but if the new serializable feature is not needed, it is recommended to continue using 1.0 which comes with a standard CAS client jar.

It uses CAS Java Client which is a less complicated client library with fewer dependencies compared to another Java client called CAS Client for Java. Although the latter is developed with Spring Framework in mind, I think in many use cases the Yale version is easier to get integrated.

On the other hand, if a more integrated security solution is needed with support for CAS, the Acegi plugin for Grails is probably more suitable,

In general, this plugin is for applications needing simple and easy authentication against CAS, without complex requirements on authorization as authorization is yet to be added in CAS (at least prior to CAS 3.1).

Prerequisite

The plugin is developed with Grails 0.6 as a start but should be compatible with versions above 0.6. Specifically it depends on the new configuration facility introduced in that release. Applications developed with Grails releases prior to 0.6 is NOT supported at the moment and there is no plan to support them in the future unfortunately because of the lack of suitable configuration options; It is though possible to edit web.template.xml directly to add CAS client support. From 0.6 onwards, using this plugin seems to be the only way and in fact, it is much better than editing web.template.xml, in terms of project staging and code maintanenance.

More details of how to understand and write your own CAS configuration can be found in Grails config page.

Installation

As a Grails plugin, it couldn't be easier to install it. 'grails install-plugins' should be able to take care of that from either locally downloaded file or remote plugin repository.

grails list-plugins
should give you a list of available plugins.
grails install-plugin cas-client [current-release-version]
should install this plugin from remote repository.
grails install-plugin /path/to/local/cas/cliet/plugin.zip
will install from a locally downloaded file.

Usage

As mentioned above, the plugin requires some extra work in Config.groovy to make CAS server and local parameters known to the plugin. So in application's Config.groovy you may add some lines of code below,

// cas client configuration, required by CasClientPlugin
cas {
urlPattern = '/someurl/*'
// urlPattern = ['/oneurl/*', '/another', '/anotheranother/*']
disabled = false
}
environments {
development {
cas.loginUrl = 'https://dev.casserver.demo.com/cas/login'
cas.validateUrl = 'https://dev.casserver.demo.com/cas/serviceValidate'
cas.serverName = 'dev.casclient.demo.com:80'
// cas.serviceUrl = 'http://dev.casclient.demo.com/access'
cas.disabled = true
cas.mocking = true
}
test {
cas.loginUrl = 'https://test.casserver.demo.com/cas/login'
cas.validateUrl = 'https://test.cas.com/cas/serviceValidate'
cas.serverName = 'test.casclient.demo.com:80'
// cas.serviceUrl = 'http://test.casclient.demo.com/access'
}
production {
cas.loginUrl = 'https://prod.casserver.demo.com/cas/login'
cas.validateUrl = 'https://prod.casserver.demo.com/cas/serviceValidate'
cas.serverName = 'prod.casclient.demo.com:80'
// cas.serviceUrl = 'http://prod.casclient.demo.com/access'
}
}
The code above should give you a quick start, by replacing those URLs. (Please note either 'cas.serverName' or 'cas.serviceUrl' should be made available but not both; Other parameters are all required. 'cas.urlPattern' can be either String or List depending on how many resources you want to protect.)

As the CAS client library used by the plugin supports more parameters, the plugin also accepts those. It checks the availability of those optional parameters and fill them in web.xml if necessary. Please refer to the table below for details.

Config.groovyRequired or Optionalweb.xml (generated by the plugin)
cas.urlPatternrequired<url-pattern/> in CAS filter's <filter-mapping/> (multiple values allowed by defining a list)
cas.loginUrlrequiredvalue for 'edu.yale.its.tp.cas.client.filter.loginUrl' as <init-param/> for CAS filter's <filter/>
cas.validateUrlrequiredvalue for 'edu.yale.its.tp.cas.client.filter.validateUrl' as <init-param/> for CAS filter's <filter/>
cas.serverNamerequired*value for 'edu.yale.its.tp.cas.client.filter.serverName' as <init-param/> for CAS filter's <filter/>
cas.serviceUrlrequired*value for 'edu.yale.its.tp.cas.client.filter.serviceUrl' as <init-param/> for CAS filter's <filter/>
cas.proxyCallbackUrloptionalvalue for 'edu.yale.its.tp.cas.client.filter.proxyCallbackUrl' as <init-param/> for CAS filter's <filter/>
cas.authorizedProxyoptionalvalue for 'edu.yale.its.tp.cas.client.filter.authorizedProxy' as <init-param/> for CAS filter's <filter/>
cas.renewoptionalvalue for 'edu.yale.its.tp.cas.client.filter.renew' as <init-param/> for CAS filter's <filter/>
cas.redirectoptionalvalue for 'edu.yale.its.tp.cas.client.filter.redirect' as <init-param/> for CAS filter's <filter/> NEW in 1.1
cas.wrapRequestoptionalvalue for 'edu.yale.its.tp.cas.client.filter.wrapRequest' as <init-param/> for CAS filter's <filter/>
* one of 'cas.serverName' and 'cas.serviceUrl' must be available but not both

Last but not least, there are parameters to control the plugin instead of the behaviour of underlying CAS client library:

Config.groovyRequired or OptionalDefaultPurpose
cas.disabledoptionalfalseThis param will turn the plugin on/off. If it is not available or its value is a boolean 'false', the plugin will work as it should be; If the value is a boolean 'true', the plugin will sense that and will not be functioning. It may be helpful in development stage.
cas.mockingoptionalfalseThis param is to enable/disable mocking of cas-ified user session. If it is available and its value is a boolean 'true', /cas?u=[username] is available for access which sets a session attribute to simulate a user who has passed CAS server authentication, with the given username. Obviously it is only useful when 'cas.disabled' is 'true'. It may be helpful in development stage sometimes and please use it very carefully when turn it on in test or even production environments as it opens a big security hole.

Examples

Simple Solution for Authorization

First of all, as users of JA-SIG CAS may already know, CAS is only for authentication but not for authorization (up to 3.x). Therefore authorization is down to users to implement, if necessary. A common pattern is to use the interceptors available with Grails,

For instance, you can have a controller AccessController like this, with this plugin installed

import edu.yale.its.tp.cas.client.filter.CASFilter

class AccessController {

def beforeInterceptor = [action: this.&check]

def check() { def username = session?.getAttribute(CASFilter.CAS_FILTER_USER) // check username and return a boolean accordingly. // … } }

Please note it looks different from the example controller showed in Grails user guide for before interceptors because:
  • it is not necessary to use 'except' to exclude a login or register page as some or all the resources in your application are protected by this plugin
  • it is not necessary to have your own session attribute to save current username as the plugin (actually the CAS client library) has done that for you
To take the above example further, a simpler solution is available,

In Config.groovy you can have a list of users allowed to access your application,

users = ['foo', 'bar']
and then the 'check' method above will look like,
def check() {
def username = session?.getAttribute(CASFilter.CAS_FILTER_USER)?.toLowerCase()
return username in grailsApplication.config.users
}
That could be helpful if your application has a simple authorization need.

Handling Large Number of Protected URLs

The plugin can handle a list of urls using 'cas.urlPattern' but it can be quite messy to list every one of them. Thanks to Re:-CAS-Client-Plugin-Doesn't-Respect-error.gspp16202152.html" class="pageLink">this mailing list post, you can group all the urls to be protected by the plugin using Grails URL mappings feature and then feed the url pattern after mapping to the plugin.

Misc.

CHANGELOG

  • 1.2 release, refactored mocking from using cas.gsp to CasController which avoids trouble when upgrading between plugin versions; also the jar that comes with this release is modified from official cas-client-2.1.1 with serializable CASReceipt class so that in environments where sessions are to be serialized this plugin would still work.
  • 1.1 release, added a feature 'redirect' which strips out CAS ticket parameter by redirecting again to same url in order to make final url bookmarkable; use with caution as redirecting is always a tricky issue.
  • 1.0 release inline with Grails 1.0, fixed a problem reported here and adding 'cas.mocking' option as previously mentioned in TODO list.
  • 0.2 updated release, added support for list as value of 'cas.urlPattern'.
  • 0.1 initial release, developed and tested against Grails 0.6.

TODO

  • upgrade to coming new release of the cas client library which contains a simple authorization utility that can replace the trick mentioned in the example above.
Also pls submit your suggestions to Grails users list.

Suggestions or Comments

Please feel free to submit them in Grails users mailing list.

Alternatively you can contact the author of the plugin directly, Chen Wang, contact at chenwang dot org