add method for plugins to easily inject into the delegated auth workflow
refs #5948 adjust specs so that if a login does inject themselves in by adding additonal redirects, we keep following them Change-Id: I16e616066ea1bef1aa5ed97718cbd8ddbd2c27c5 Reviewed-on: https://gerrit.instructure.com/6536 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com> Reviewed-by: Brian Palmer <brianp@instructure.com>
This commit is contained in:
parent
b9981e4b9c
commit
794d59eef9
|
@ -72,8 +72,9 @@ class PseudonymSessionsController < ApplicationController
|
|||
return
|
||||
else
|
||||
logger.warn "Received CAS login for unknown user: #{st.response.user}"
|
||||
reset_session
|
||||
session[:delegated_message] = t 'errors.no_matching_user', "Canvas doesn't have an account for user: %{user}", :user => st.response.user
|
||||
redirect_to :action => :destroy
|
||||
redirect_to(cas_client.logout_url(login_url :no_auto => true))
|
||||
return
|
||||
end
|
||||
else
|
||||
|
@ -88,6 +89,7 @@ class PseudonymSessionsController < ApplicationController
|
|||
elsif @is_saml && !params[:no_auto]
|
||||
initiate_saml_login(request.env['canvas.account_domain'])
|
||||
end
|
||||
flash[:delegated_message] = session.delete :delegated_message
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -241,11 +241,11 @@ module AuthenticationMethods
|
|||
reset_session_for_login
|
||||
if @domain_root_account.account_authorization_config.log_in_url.present?
|
||||
session[:exit_frame] = true
|
||||
redirect_to(@domain_root_account.account_authorization_config.log_in_url)
|
||||
delegated_auth_redirect(@domain_root_account.account_authorization_config.log_in_url)
|
||||
else
|
||||
config = { :cas_base_url => @domain_root_account.account_authorization_config.auth_base }
|
||||
cas_client ||= CASClient::Client.new(config)
|
||||
redirect_to(cas_client.add_service_to_login_url(login_url))
|
||||
delegated_auth_redirect(cas_client.add_service_to_login_url(login_url))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -253,6 +253,10 @@ module AuthenticationMethods
|
|||
reset_session_for_login
|
||||
settings = @domain_root_account.account_authorization_config.saml_settings(preferred_account_domain)
|
||||
request = Onelogin::Saml::AuthRequest.create(settings)
|
||||
redirect_to(request)
|
||||
delegated_auth_redirect(request)
|
||||
end
|
||||
|
||||
def delegated_auth_redirect(uri)
|
||||
redirect_to(uri)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -127,90 +127,5 @@ describe PseudonymSessionsController do
|
|||
session[:cas_login].should == true
|
||||
Pseudonym.find(session[:pseudonym_credentials_id]).should == user2.pseudonyms.first
|
||||
end
|
||||
|
||||
it "should log in and log out a user CAS has validated" do
|
||||
account = account_with_cas({:account => Account.default})
|
||||
user = user_with_pseudonym({:active_all => true})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to(controller.cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
stubby("yes\n#{user.pseudonyms.first.unique_id}\n", false)
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should redirect_to(dashboard_url(:login_success => 1))
|
||||
session[:cas_login].should == true
|
||||
|
||||
get 'destroy'
|
||||
response.should redirect_to(controller.cas_client.logout_url(login_url))
|
||||
end
|
||||
|
||||
it "should inform the user CAS validation denied" do
|
||||
account = account_with_cas({:account => Account.default})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to(controller.cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
stubby("no\n\n", false)
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should redirect_to(:action => 'new', :no_auto => true)
|
||||
flash[:delegated_message].should match(/There was a problem logging in/)
|
||||
end
|
||||
|
||||
it "should inform the user CAS validation failed" do
|
||||
account = account_with_cas({:account => Account.default})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to(controller.cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
cas_client = controller.cas_client
|
||||
def cas_client.validate_service_ticket(st)
|
||||
raise "Nope"
|
||||
end
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should redirect_to(:action => 'new', :no_auto => true)
|
||||
flash[:delegated_message].should match(/There was a problem logging in/)
|
||||
end
|
||||
|
||||
it "should inform the user that CAS account doesn't exist" do
|
||||
account = account_with_cas({:account => Account.default})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to(controller.cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
stubby("yes\nnonexistentuser\n")
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should redirect_to(:action => 'destroy')
|
||||
get 'destroy'
|
||||
response.should redirect_to(:action => 'new', :no_auto => true)
|
||||
flash[:delegated_message].should match(/Canvas doesn't have an account for user/)
|
||||
end
|
||||
|
||||
it "should redirect to alternate CAS login page if so configured, and frame bust on login" do
|
||||
account = account_with_cas({:account => Account.default, :cas_log_in_url => 'http://example.com/cas'})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to('http://example.com/cas')
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should render_template('shared/exit_frame')
|
||||
end
|
||||
|
||||
it "should login case insensitively" do
|
||||
account = account_with_cas({:account => Account.default})
|
||||
user = user_with_pseudonym({:active_all => true})
|
||||
|
||||
get 'new'
|
||||
response.should redirect_to(controller.cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
stubby("yes\n#{user.pseudonyms.first.unique_id.capitalize}\n")
|
||||
|
||||
get 'new', :ticket => 'ST-abcd'
|
||||
response.should redirect_to(dashboard_url(:login_success => 1))
|
||||
session[:cas_login].should == true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
#
|
||||
# Copyright (C) 2011 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
||||
|
||||
describe PseudonymSessionsController do
|
||||
def redirect_until(uri)
|
||||
count = 0
|
||||
while true
|
||||
response.should be_redirect
|
||||
return if response.location == uri
|
||||
count += 1
|
||||
count.should < 5
|
||||
follow_redirect!
|
||||
end
|
||||
end
|
||||
|
||||
context "cas" do
|
||||
def stubby(stub_response)
|
||||
@cas_client = CASClient::Client.new({:cas_base_url => @account.account_authorization_config.auth_base})
|
||||
@cas_client.instance_variable_set(:@stub_response, stub_response)
|
||||
def @cas_client.validate_service_ticket(st)
|
||||
st.response = CASClient::ValidationResponse.new(@stub_response)
|
||||
end
|
||||
PseudonymSessionsController.any_instance.stubs(:cas_client).returns(@cas_client)
|
||||
end
|
||||
|
||||
it "should log in and log out a user CAS has validated" do
|
||||
account_with_cas({:account => Account.default})
|
||||
user = user_with_pseudonym({:active_all => true})
|
||||
|
||||
stubby("yes\n#{user.pseudonyms.first.unique_id}\n")
|
||||
|
||||
get login_url
|
||||
redirect_until(@cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should redirect_to(dashboard_url(:login_success => 1))
|
||||
session[:cas_login].should == true
|
||||
|
||||
get logout_url
|
||||
response.should redirect_to(@cas_client.logout_url(login_url))
|
||||
end
|
||||
|
||||
it "should inform the user CAS validation denied" do
|
||||
account_with_cas({:account => Account.default})
|
||||
|
||||
stubby("no\n\n")
|
||||
|
||||
get login_url
|
||||
redirect_until(@cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should redirect_to(login_url :no_auto => true)
|
||||
flash[:delegated_message].should match(/There was a problem logging in/)
|
||||
end
|
||||
|
||||
it "should inform the user CAS validation failed" do
|
||||
account_with_cas({:account => Account.default})
|
||||
|
||||
stubby('')
|
||||
def @cas_client.validate_service_ticket(st)
|
||||
raise "Nope"
|
||||
end
|
||||
|
||||
get login_url
|
||||
redirect_until(@cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should redirect_to(login_url :no_auto => true)
|
||||
flash[:delegated_message].should match(/There was a problem logging in/)
|
||||
end
|
||||
|
||||
it "should inform the user that CAS account doesn't exist" do
|
||||
account_with_cas({:account => Account.default})
|
||||
|
||||
stubby("yes\nnonexistentuser\n")
|
||||
|
||||
get login_url
|
||||
redirect_until(@cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should redirect_to(@cas_client.logout_url(login_url :no_auto => true))
|
||||
get login_url :no_auto => true
|
||||
flash[:delegated_message].should match(/Canvas doesn't have an account for user/)
|
||||
end
|
||||
|
||||
it "should redirect to alternate CAS login page if so configured, and frame bust on login" do
|
||||
account_with_cas({:account => Account.default, :cas_log_in_url => 'http://example.com/cas'})
|
||||
|
||||
get login_url
|
||||
redirect_until('http://example.com/cas')
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should render_template('shared/exit_frame')
|
||||
end
|
||||
|
||||
it "should login case insensitively" do
|
||||
account_with_cas({:account => Account.default})
|
||||
user = user_with_pseudonym({:active_all => true})
|
||||
|
||||
stubby("yes\n#{user.pseudonyms.first.unique_id.capitalize}\n")
|
||||
|
||||
get login_url
|
||||
redirect_until(@cas_client.add_service_to_login_url(login_url))
|
||||
|
||||
get login_url :ticket => 'ST-abcd'
|
||||
response.should redirect_to(dashboard_url(:login_success => 1))
|
||||
session[:cas_login].should == true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -83,25 +83,25 @@ Spec::Runner.configure do |config|
|
|||
end
|
||||
|
||||
def account_with_cas(opts={})
|
||||
account = opts[:account]
|
||||
account ||= Account.create!
|
||||
@account = opts[:account]
|
||||
@account ||= Account.create!
|
||||
config = AccountAuthorizationConfig.new
|
||||
cas_url = opts[:cas_url] || "https://localhost/cas"
|
||||
config.auth_type = "cas"
|
||||
config.auth_base = cas_url
|
||||
config.log_in_url = opts[:cas_log_in_url] if opts[:cas_log_in_url]
|
||||
account.account_authorization_configs << config
|
||||
account
|
||||
@account.account_authorization_configs << config
|
||||
@account
|
||||
end
|
||||
|
||||
def account_with_saml(opts={})
|
||||
account = opts[:account]
|
||||
account ||= Account.create!
|
||||
@account = opts[:account]
|
||||
@account ||= Account.create!
|
||||
config = AccountAuthorizationConfig.new
|
||||
config.auth_type = "saml"
|
||||
config.log_in_url = opts[:saml_log_in_url] if opts[:saml_log_in_url]
|
||||
account.account_authorization_configs << config
|
||||
account
|
||||
@account.account_authorization_configs << config
|
||||
@account
|
||||
end
|
||||
|
||||
def course(opts={})
|
||||
|
|
Loading…
Reference in New Issue