My solution is like the following:
I have a system called Central
, in which I manage the users and their passwords using Devise
, Ruby-CAS-Server
system performs the authentication against this database, and CanCan
and Ruby-CAS-Client
is used to manage the authorizations and authentication.
And I have several other systems, for example called Satellite
, which authenticates using CAS and only have a simple User
Class to hold the properties coming from CAS after authentication, and CanCan
to manage authorizations, and no Devise
is used.
###Central
ApplicationController
in Central
:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :cas_auth
def sign_out
Devise.sign_out_all_scopes # To signout
CASClient::Frameworks::Rails::Filter.logout(self) # Also to logout from CAS.
end
def cas_auth
# if the user is not logged in and there's info in the session after cas logged in, sign the user in.
if session['cas_user'] && !user_signed_in?
@user = User.find_by_username(session['cas_user'])
sign_in_and_redirect @user, :event => :authentication
else
# direct the user to CAS to perform the authentication.
CASClient::Frameworks::Rails::Filter.filter(self)
end
end
...
end
Ability.rb
in Central
:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :manage, [User, Organization, Department] if user.is? :admin
can :read, User if user.is? :user
can :read, User if user.is? :author
can :update_seq, User
end
end
###Satellite
application_controller.rb
in Satellite
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :cas_filter, :current_user
def sign_out
CASClient::Frameworks::Rails::Filter.logout(self)
end
def current_user
unless @current_user
@current_user = User.new(
session['cas_extra_attributes']['name'], session['cas_extra_attributes']['email'],
session['cas_user'], session['cas_extra_attributes']['ziya_news_role'], session['cas_extra_attributes']['news_manage_cats'],
session['cas_extra_attributes']['news_read_cats']
)
else
@current_user
end
end
def cas_filter
CASClient::Frameworks::Rails::Filter.filter(self)
end
...
end
User.rb
in Satellite
class User
attr_accessor :name, :email, :username, :role, :news_manage_cats, :news_read_cats
def initialize(name, username, email, role, news_manage_cats, news_read_cats)
self.name = name
self.email = email
self.username = username
self.role = role
self.news_manage_cats = news_manage_cats
self.news_read_cats = news_read_cats
end
def is?(role)
self.role == role.to_s
end
end