Skip to content

Bootcamp Day One May 11

harleyttd edited this page Sep 13, 2010 · 1 revision

CAS authentication

Install RubyCAS plugin

(if the following doesn’t work for you, you can install RubyCAS as a gem (sudo gem install rubycas-client) or install from a http path (./script/plugin install http://rubycas-client.googlecode.com/svn/trunk/rubycas-client). It’s a good habit to skim the documentation to know what this does: http://github.com/gunark/rubycas-client/tree/master (scroll down for installation and usage examples)

./script/plugin install git://github.com/gunark/rubycas-client.git

before_filter and skip_before_filter

Put this in your application.rb

before_filter CASClient::Frameworks::Rails::Filter


What this does is to redirect the user to the CAS server if he’s not logged in or his CAS session has expired. Because it’s put in application.rb, all controllers inherit this so all actions are protected. If you have a controller where you want to bypass the authentication, then use skip_before_filter with the same argument which takes this one out of the list of methods added for a controller’s before_filter (i.e. it only skips the filter method you specify, and other filter methods still apply)
Both before_filter and skip_before_filter take take additional arguments in the hash form, with keys as :only or :except and value as action name or list of action names. E.g.

<pre>

  1. this makes action index bypass authentication
    skip_before_filter CASClient::Frameworks::Rails::Filter, :only => :index
  2. you can also pass in a list
    skip_before_filter CASClient::Frameworks::Rails::Filter, :only => [:index, :show]
  3. this only requires action destroy to check authentication
    skip_before_filter CASClient::Frameworks::Rails::Filter, :except => :destroy


    Logout


    As you can see from the RubyCAS documentation page, here’s how to define a logout action


    <pre> def logout reset_session CASClient::Frameworks::Rails::Filter.logout(self) end </pre>

Sessions allows you to store objects in between requests. This is how an web application knows if you’re logged in or not. This is the preferred way over using browser’s cookies. To enable sessions in rails, read page 107 on the Agile Rails pdf
So reset_session clear the session content in the database so our application thinks that you’re logged out and thus the next time a request for an action that has CAS before_filter, it sends you to the CAS server again. However the CAS server may not ask you to enter password again because you only recently logged in from the same browser. To make sure logout does not desired thing: one must re-enter netid and password to login, you also need the line CASClient::Frameworks::Rails::Filter.logout(self) which also takes you to the CAS logout page.

The current_user method

Put this method in your application.rb
<pre> def current_user @current_user ||= User.find_by_netid(session[:cas_user]) || User.import_from_ldap(session[:cas_user], true) end </pre>


First note the ||= operator. In Ruby (and many other modern languages), a ||= b is the same as a = a || b which means that if a is nil or False, assign b to a, otherwise value of a does not change. Here I use both a || b and a ||= b in the form of a ||= b || c. Please read page 678 on the Agile Rails pdf for more on useful Ruby idioms that you will need to use frequently.

To make the current_user method available for view files (e.g. in helper methods and in html.erb files), put this in application.rb (below the class definition line class ApplicationController < ... )

LDAP

So CAS authentication basically requires the user to put in netid and password and all it returns to our application is the netid stored in session[:cas_user]. In order to know who the user is, we need to look him/her up by netid in our database. Alas, what if we don’t have that user in the database but he’s a valid CAS user (in our case, anybody at Yale). We can just look him up in the phonebook, Please see the method import_from_ldap in the user.rb file in the source code. Note that you need to install the ‘ruby-net-ldap’ gem and put a require 'net/ldap' line on top of user.rb. If there’s any problem, try adding require 'rubygems' before it. In any case, if you have a problem somewhere, please ask.

You can test if import_from_ldap works or not from the command line, fire up ruby script/console and type a = User.import_from_ldap("abc123") and then investigate the content of a. To investigate the content of any object, for example a, you can just type y a.

y is a debugging method that prints the yaml dump of that object, so it’s the same thing as puts a.to_yaml

Data dump

We also covered data dumping technique. Go to http://github.com/adamwiggins/yaml_db/tree/master for usage examples. To install it as a plugin:

ruby script/plugin install git://github.com/adamwiggins/yaml_db.git


You will find this useful later on because we will be checking code in to a version control system, which we don’t check in the database content. So it’d be nice to dump the data out to a text file and check it in the system so somebody else can load the database from that file. This is also useful if you decide switch from sqlite3 to mysql on your machine for example, in which case just dump data, create new database, and then load data again. Please go to the above link for more explanation.