redirect to discovery page for unauthenticated deep links

refs #CNVS-2174

found the bit in the authorization sequence where
saml login was being initiated without checking
for a discovery url.  Fixed that, and also wrote
some unit tests around it.

ended up having to alter specs a bit to deal
with the extensions added by the
canvas_zendesk_plugin

TEST PLAN:
1) select an account that is authenticated with SAML
2) without logging in, attempt to hit a 'deep
  link' on that domain with the browser (any url
  that isn't the login page would be fine, as long
  as it's something you must be logged in to access)
3) you should be redirected to the SAML discovery page

Change-Id: Id9c21650d8c053178d4d40ff064051af79c5eb2f
Reviewed-on: https://gerrit.instructure.com/16355
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Ethan Vizitei <ethan@12spokes.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
QA-Review: Clare Hetherington <clare@instructure.com>
This commit is contained in:
Ethan Vizitei 2012-12-26 13:55:44 -06:00
parent 35ab5f675b
commit e3e7c0d0e5
3 changed files with 142 additions and 4 deletions

View File

@ -228,13 +228,19 @@ module AuthenticationMethods
def initiate_delegated_login(current_host=nil)
is_delegated = @domain_root_account.delegated_authentication? && !params[:canvas_login]
is_cas = @domain_root_account.cas_authentication? && is_delegated
is_saml = @domain_root_account.saml_authentication? && is_delegated
is_cas = is_delegated && @domain_root_account.cas_authentication?
is_saml = is_delegated && @domain_root_account.saml_authentication?
if is_cas
initiate_cas_login
return true
elsif is_saml
initiate_saml_login(current_host)
if @domain_root_account.auth_discovery_url
redirect_to @domain_root_account.auth_discovery_url
else
initiate_saml_login(current_host)
end
return true
end
false

View File

@ -115,6 +115,18 @@ describe PseudonymSessionsController do
end
end
context "SAML" do
it 'redirects to the discovery page when hitting a deep link while unauthenticated' do
account = account_with_saml( :account => Account.default )
discovery_url = 'http://discovery-url.example.com'
account.auth_discovery_url = discovery_url
account.save!
get account_account_authorization_configs_url(account)
redirect_until(discovery_url)
end
end
it "should redirect back for jobs controller" do
user_with_pseudonym(:password => 'qwerty', :active_all => 1)
Account.site_admin.add_user(@user)
@ -125,4 +137,4 @@ describe PseudonymSessionsController do
post login_url, :pseudonym_session => { :unique_id => @pseudonym.unique_id, :password => 'qwerty' }
response.should redirect_to jobs_url
end
end
end

View File

@ -0,0 +1,120 @@
require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe AuthenticationMethods do
describe '#initiate_delegated_login' do
let(:request) { stub(:host_with_port => '' ) }
let(:controller) { Spec::MockController.new(domain_root_account, request) }
describe 'when auth is not delegated' do
let(:domain_root_account) { stub(:delegated_authentication? => false) }
it 'returns false' do
controller.initiate_delegated_login.should be_false
end
it 'does not redirect anywhere' do
controller.initiate_delegated_login
controller.redirects.should == []
end
end
describe 'when auth is CAS' do
let(:domain_root_account) do
stub(
:delegated_authentication? => true,
:cas_authentication? => true,
:saml_authentication? => false,
:account_authorization_config => stub(:auth_base => 'base_url')
)
end
it 'returns true' do
controller.initiate_delegated_login.should be_true
end
it 'redirects to CAS client url' do
client = stub(:add_service_to_login_url => 'cas_login_url')
CASClient::Client.stubs(:new => client)
controller.initiate_delegated_login
controller.redirects.should == ['cas_login_url']
end
it 'can be overriden by passing the canvas_login parameter' do
controller = Spec::MockController.new(domain_root_account, request, :canvas_login => true)
controller.initiate_delegated_login.should be_false
controller.redirects.should == []
end
end
describe 'when auth is SAML' do
let(:domain_root_account) do
stub(
:delegated_authentication? => true,
:cas_authentication? => false,
:saml_authentication? => true,
:account_authorization_config => stub(:saml_settings => {}, :debugging? => false),
:auth_discovery_url => nil
)
end
let(:saml_request) { stub(:generate_request => 'saml_login_url') }
before do
Onelogin::Saml::AuthRequest.stubs(:new => saml_request)
end
it 'returns true' do
controller.initiate_delegated_login.should be_true
end
it 'redirects to SAML auth request url' do
controller.initiate_delegated_login
controller.redirects.should == ['saml_login_url']
end
it 'redirects to the discovery url if there is one' do
domain_root_account.stubs(:auth_discovery_url => 'discovery_url')
controller.initiate_delegated_login
controller.redirects.should == ['discovery_url']
end
it 'can be overriden by passing the canvas_login parameter' do
controller = Spec::MockController.new(domain_root_account, request, :canvas_login => true)
controller.initiate_delegated_login.should be_false
controller.redirects.should == []
end
end
end
end
class Spec::MockController
include AuthenticationMethods
attr_reader :redirects, :params, :session, :request
def initialize(root_account, req, params_hash = {})
@domain_root_account = root_account
@request = req
@redirects = []
@params = params_hash
reset_session
end
def reset_session
@session = {}
end
def redirect_to(url)
@redirects << url
end
def cas_login_url; ''; end
def zendesk_delegated_auth_pass_through_url(options)
options[:target]
end
end