With restful_authentication (or other schemes) we have a requires_login before_filter which you stick at the top of your controllers, to make sure certain actions are protected by login. It also tends to take care of the slightly messy logic involved in setting up the extremely useful current_user variable.
Obviously our applications have already been built around this logic existing, so a smooth transition requires the same sort of functionality.
The ruby-CAS (client) provides a basic before_filter for us that takes care of the nasty talking-to-the-rubyCAS-server logic... at the end of which we know whether or not the person talking to us is known to the system. But we still to actually associate this person with a real live User model on our system, and save them into the current-user variable.
On our system, after going through the provided before_filter, we have configured the server to provide two things in the session:
- the :cas_user, which is the user's username and
- a set of :extra_attributes which is a set of other fields we've asked CAS to provide and which we'll use later for roles (see authorisation for more on that)
If we want any other user information - we will need to go fetch it by hand from our local db, and we'll need to do this directly after the main rubyCAS before_filter. So, we'll need something like the following, probably put into ApplicationController
# this is the before_filter provided by rubyCAS client before_filter CASClient::Frameworks::Rails::Filter # this is a call to our own new before_filter before_filter :setup_cas_user # actions go here... # and at the bottom of the controller file... private # this before_filter takes the results of the rubyCAS-client filter and sets up the current_user def setup_cas_user # save the login_url into an @var so that we can later use it in views (eg a login form) @login_url = CASClient::Frameworks::Rails::Filter.login_url(self) # if we don't have the :cas_user in the session, then we are not logged into rubyCAS # we could have none because: # 1) we have failed login or # 2) because we don't necessarily need to login to get here # either way we need to skip out here return unless session[:cas_user].present? # so now we go find the user in our db @current_user = User.find_by_username(session[:cas_user]) @current_user.present? end
Pretty simple
What if the user isn't on this application yet?
Good question - it is possible to have created a user on one application and of course, using single sign-on, you may want to automatically sign your users up into another application. This could easily be done here with a slight addition to the before_filter:
# so now we go find the user in our db - or create them if they don't yet exist. @current_user = User.find_or_create_by_username(session[:cas_user]) @current_user.present?
Note: the only information linking the two user-records will be the username. You won't be able to access any other information (eg address or other details) unless you physically query your other application's user record... though this is a good use-case for passing extra information through the extra_attributes fields. Still, it does allow your users to seamlessly transition from one of your applications to another.
This is one article in a series on Rails single-sign-on with rubyCAS