Skip to content

Instantly share code, notes, and snippets.

@larryzhao
Last active December 22, 2015 03:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larryzhao/6414124 to your computer and use it in GitHub Desktop.
Save larryzhao/6414124 to your computer and use it in GitHub Desktop.
Devise+CanCan+RubyCAS

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment