oreilly.comSafari Books Online.Conferences.


CAS+: Single Sign-On With Jifty (Part 2)
Pages: 1, 2, 3, 4

Lots of tickets

Okay, I chose not to explain much about the models in Part 1 of this article, but there are enough "tickets" involved that I thought it might help to see the basics of how these are stored in CAS+. It also shows off the declarative syntax Jifty uses to declare its data models.

SSO session

The SSO session is stored in CASPlus::Model::SSOSession. This is the basic building block for authentication. Here is the abbreviated Jifty::DBI model declaration:

column authenticated_user => 
    refers_to CASPlus::Model::User;
column ticket_granting_cookie => 
    type is 'text', is mandatory, is distinct;
column current_valid_ticket => 
    type is 'boolean', default is 1;

An SSO Session record is created once the user has logged in. At that time, a cookie is set in the browser's cookie stash containing the ticket_granting_cookie identifier. By looking up the ticket_granting_cookie, the system can now who the user is by looking it up in authenticated_user. If the user logs out (not discussed in my articles, but part of the CAS protocol), the current_valid_ticket is changed to false and all other sessions associated with it are immediately invalid.

Service session

The service session is stored in CASPlus::Model::ServiceSession. When a web service redirects the browser to the CAS server, a service session is created once the user's identity is verified and the Service Ticket referring to this session is returned to the client web service.

Here's the abbreviated declaration:

column sso_session => 
    refers_to CASPlus::Model::SSOSession;
column service_url => 
    type is 'text', is mandatory;
column service_ticket => 
    type is 'text', is mandatory, is distinct;
column current_valid_ticket => 
    type is 'boolean', default is 1;
column expiration_time => 
    type is 'timestamp', is mandatory;

Once the client web service receives the Service Ticket, it will perform a validation of that ticket. CAS looks up the Service Ticket in the service_ticket column and returns the username associated with the authenticated_user column of the linked sso_session record. It also sets current_valid_ticket to false so that validation can't be made against the same ticket twice. Finally, if validation is attempted after expiration_time, the validation will fail (there's a 5 minute time limit between requesting the service ticket and performing validation).

Proxy grant session

The proxy grant session is stored in CASPlus::Model::ProxyGrantSession. When a callback URL is specified during Service Ticket or Proxy Ticket validation, a proxy grant session record is created. Here's the abbreviated declaration of the model:

column service_session => 
    refers_to CASPlus::Model::ServiceSession;
column proxy_session => 
    refers_to CASPlus::Model::ProxySession;
column callback_url => 
    type is 'text';
column proxy_granting_iou => 
    type is 'text', is mandatory, is distinct;
column proxy_granting_ticket => 
    type is 'text', is mandatory, is distinct;

Later, when a Proxy Ticket is requested, the system looks up the SSO session associated with service_session to make sure it is still valid and then returns a new Proxy Ticket. When Proxy Ticket validation occurs, the chain of proxy_session records is read and returned in the response.

Proxy session

The proxy session is stored in CASPlus::Model::ProxySession. A proxy session is created as soon as a web service or application owning a Proxy Granting Ticket requests a Proxy Ticket. Here's the abbreviated declaration:

column proxy_grant_session => 
    refers_to CASPlus::Model::ProxyGrantSession;
column proxy_ticket => 
    type is 'text', is mandatory, is distinct;
column service_identifier => 
    type is 'text', is mandatory;
column current_valid_ticket => 
    type is 'boolean', default is 1;
column expiration_time => 
    type is 'timestamp', is mandatory;

During validation, the proxy_grant_session is used to determine if the parent SSO session is still valid and to fetch the username of the authenticated user. The service_identifier is the same as the service session's service_url, except that they don't have to be URLs since proxied applications often don't have a web address. The current_valid_ticket and expiration_time are used in the same way as they are in the service session.

What Else?

The CAS 3.0 version of this protocol doesn't really change the mechanisms so much as it creates places where the messages can be modified or added to. Many CAS administrators need features like "single sign-off" where each service is notified immediately by callback when user's log out. Some want CAS to handle additional data storage of profile information, roles and permissions, or Access Control Lists. CAS 3.0 provides mechanisms for adding customizations for this purpose. I'm (slowly) working to add facilities for these to the CAS+ implementation as well.

Distributed Authentication

Another related method of authentication that is growing in popularity is distributed authentication. Protocols, such as OpenID, allow a user known on one system to login to systems all over the web without the other systems having an explicit trust relationship. This is nice because it allows the user even more control over authentication and allows a user who has an account on multiple systems to login to all of those systems just by logging into their blog or corporate web site.

I'm hoping to add OpenID support to CAS+ at some point as well. It could act as both a consumer of OpenID data (signing in elsewhere via an associated OpenID account is enough to sign-in to any service trusting your CAS server) and as a provider where other OpenID servers can use CAS+ to identify users.

CAS is a very simple protocol for all the features it provides. I was pleasantly surprised to find out how easy it was to implement and am somewhat surprised that there aren't more CAS server implementations available. It is very easy. I think this experiment also illustrated the inherent flexibility of Jifty. At least one developer has tried to convince me that Jifty is not very flexible and doesn't work well in unusual cases. I think this has helped to prove to Jifty is a very workable and robust framework.

Andrew Sterling Hanenkamp is a proud Kansan and spends most of his time hacking Perl, his web site, avoiding yard work, and with his wife and son.

Return to

Sponsored by: