Led & Sustained by

G2one Logo

Developed with

Intellij

Powered by

Spring

CAS Client Plugin

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.0 and it is strongly recommended to upgrade to this version. 

It uses CAS Java Client,

http://www.ja-sig.org/products/cas/client/javaclient/index.html

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 personally think it is too heavy to be 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,

http://grails.org/AcegiSecurity+Plugin

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. 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,

http://grails.org/Config

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.

Please click here  to download the latest version, in case the 'grails list-plugins' or 'grails install-plugin' is not responding.  

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.groovy

Required or Optional

web.xml  (generated by the plugin)

 cas.urlPattern required <url-pattern/> in CAS filter's <filter-mapping/> (multiple values allowed by defining a list)

 cas.loginUrl

required value for 'edu.yale.its.tp.cas.client.filter.loginUrl' as <init-param/> for CAS filter's <filter/>
 cas.validateUrl

required value for 'edu.yale.its.tp.cas.client.filter.validateUrl' as <init-param/> for CAS filter's <filter/>
 cas.serverName required*** value for 'edu.yale.its.tp.cas.client.filter.serverName' as <init-param/> for CAS filter's <filter/>
 cas.serviceUrl

required*** value for 'edu.yale.its.tp.cas.client.filter.serviceUrl' as <init-param/> for CAS filter's <filter/>
 cas.proxyCallbackUrl optional value for 'edu.yale.its.tp.cas.client.filter.proxyCallbackUrl' as <init-param/> for CAS filter's <filter/>
 cas.authorizedProxy optional value for 'edu.yale.its.tp.cas.client.filter.authorizedProxy' as <init-param/> for CAS filter's <filter/>
 cas.renew optional value for 'edu.yale.its.tp.cas.client.filter.renew' as <init-param/> for CAS filter's <filter/>
 cas.wrapRequest

optional value 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.groovy Required or Optional

Default Purpose
 cas.disabled optional false This 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 do nothing.

It may be helpful in development stage sometimes.

 cas.mocking optional false This param is to enable/disable mocking of cas-ified user session.

If it is available and its value is a boolean 'true', /cas.gsp?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 2.x). Therefore authorization is down to users to implement, if necessary. A common pattern is to use the interceptors available with Grails,

http://grails.org/Controllers+-+Interceptors

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 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.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.

http://grails.org/Mailing+lists

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

</