Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom failure class for optional redirecting to logout url upon timeout #67

Merged
merged 1 commit into from
May 8, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,16 @@ to tell your app how to talk to your CAS server:
# By default, devise_cas_authenticatable will create users. If you would rather
# require user records to already exist locally before they can authenticate via
# CAS, uncomment the following line.
# config.cas_create_user = false
# config.cas_create_user = false

# If you want to use the Devise Timeoutable module with single sign out,
# uncommenting this will redirect timeouts to the logout url, so that the CAS can
# take care of signing out the other serviced applocations. Note that each
# application manages timeouts independently, so one application timing out will
# kill the session on all applications serviced by the CAS.
# config.warden do |manager|
# manager.failure_app = DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp
# end
end

Extra attributes
Expand Down
2 changes: 1 addition & 1 deletion devise_cas_authenticatable.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ Gem::Specification.new do |s|
s.add_development_dependency("capybara")
s.add_development_dependency('crypt-isaac')
s.add_development_dependency('launchy')
s.add_development_dependency('pry')
s.add_development_dependency('timecop')
end

5 changes: 5 additions & 0 deletions lib/devise_cas_authenticatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
else
module DeviseCasAuthenticatable
class Engine < Rails::Engine
initializer "devise_cas_authenticatable.single_sign_on.warden_failure_app" do |app|
# requiring this here because the parent class calls Rails.application, which
# isn't set up until after bundler has required the modules in this engine
require 'devise_cas_authenticatable/single_sign_out/warden_failure_app'
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Redirect to the logout url when :warden is thrown,
# so that a single_sign_out request can be initiated
class DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp < Devise::FailureApp

alias :standard_scope_path :scope_path

# You need to override respond to eliminate recall
def respond
if http_auth?
http_auth
else
redirect
end
end

def redirect
store_location!
if flash[:timedout] && flash[:alert]
flash.keep(:timedout)
flash.keep(:alert)
else
flash[:alert] = i18n_message
end
redirect_to redirect_url
end

protected

def redirect_url
if warden_message == :timeout
flash[:timedout] = true
Devise.cas_client.logout_url
else
scope_path
end
end

def scope_path
standard_scope_path
end

end
2 changes: 1 addition & 1 deletion spec/scenario/app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class User < ActiveRecord::Base
devise :cas_authenticatable, :rememberable
devise :cas_authenticatable, :rememberable, :timeoutable

def active_for_authentication?
super && !deactivated
Expand Down
1 change: 1 addition & 0 deletions spec/scenario/config/initializers/devise.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Devise.setup do |config|
require "devise/orm/active_record"
config.timeout_in = 7200
end
51 changes: 51 additions & 0 deletions spec/single_sign_out_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require 'spec_helper'

describe DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp do
include RSpec::Rails::RequestExampleGroup
include Capybara::DSL

describe "A logged in user with a timed out session" do

before do
Devise.cas_base_url = "http://www.example.com/cas_server"
User.delete_all
@user = User.create!(:username => "joeuser")
end

describe "using the default warden failure app" do

before do
sign_into_cas "joeuser", "joepassword"
end

it "redirects to cas_login_url when warden is thrown" do
Devise::FailureApp.any_instance.expects(:redirect_url).returns(cas_login_url)
Timecop.travel(Devise.timeout_in) do
visit root_url
end
current_url.should == root_url
end

end

describe "using the custom WardenFailureApp" do

before do

Devise.warden_config[:failure_app] = DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp
sign_into_cas "joeuser", "joepassword"
end

it "uses the redirect_url from the custom failure class" do
DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp.any_instance.expects(:redirect_url).returns(destroy_user_session_url)
Timecop.travel(Devise.timeout_in) do
visit root_url
end
current_url.should match(/#{cas_logout_url}/)
end

end

end

end
6 changes: 3 additions & 3 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
$:.unshift File.expand_path('../../lib', __FILE__)

require "scenario/config/environment"
require "rails/test_help"
require 'rspec/rails'
require 'sham_rack'
require 'capybara/rspec'
require 'timecop'

RSpec.configure do |config|
config.mock_with :mocha
RSpec.configure do |config|
config.mock_with :mocha
end

ShamRack.at('www.example.com') do |env|
Expand Down
19 changes: 19 additions & 0 deletions spec/support/urls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
def cas_login_url
@cas_login_url ||= begin
uri = URI.parse(Devise.cas_base_url + "/login")
uri.query = Rack::Utils.build_nested_query(:service => user_service_url)
uri.to_s
end
end

def cas_logout_url
@cas_logout_url ||= Devise.cas_base_url + "/logout"
end

def sign_into_cas(username, password)
visit cas_login_url
fill_in "Username", :with => username
fill_in "Password", :with => password
click_on "Login"
current_url.should == root_url
end
41 changes: 41 additions & 0 deletions spec/warden_failure_app_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'spec_helper'

describe DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp do

describe "#redirect_url" do

before do
Devise.cas_base_url = "http://www.example.com/cas_server"
@failure_app = DeviseCasAuthenticatable::SingleSignOut::WardenFailureApp.new
@failure_app.stubs(:flash).returns({})
end

describe "resulting from a timeout" do

before do
@failure_app.stubs(:warden_message).returns(:timeout)
end

it "returns the logout url" do
@failure_app.send(:redirect_url).should match(/#{cas_logout_url}/)
end

end

describe "resulting from a generic warden :throw error" do

before do
@failure_app.stubs(:warden_message).returns(nil)
@failure_app.stubs(:flash).returns({})
end

it "calls the scope_path method to retrieve the standard redirect_url" do
@failure_app.expects(:scope_path)
@failure_app.send(:redirect_url)
end

end

end

end