diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index f642e6d47e0..362b9cc9a88 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -219,49 +219,5 @@ Devise.setup do |config| end end - Gitlab.config.omniauth.providers.each do |provider| - provider_arguments = [] - - %w[app_id app_secret].each do |argument| - provider_arguments << provider[argument] if provider[argument] - end - - case provider['args'] - when Array - # An Array from the configuration will be expanded. - provider_arguments.concat provider['args'] - when Hash - # Add procs for handling SLO - if provider['name'] == 'cas3' - provider['args'][:on_single_sign_out] = lambda do |request| - ticket = request.params[:session_index] - raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket) - - Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket) - true - end - end - - if provider['name'] == 'authentiq' - provider['args'][:remote_sign_out_handler] = lambda do |request| - authentiq_session = request.params['sid'] - if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session) - Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session) - true - else - false - end - end - end - - if provider['name'] == 'shibboleth' - provider['args'][:fail_with_empty_uid] = true - end - - # A Hash from the configuration will be passed as is. - provider_arguments << provider['args'].symbolize_keys - end - - config.omniauth provider['name'].to_sym, *provider_arguments - end + Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers) end diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb new file mode 100644 index 00000000000..35ed3a5ac05 --- /dev/null +++ b/lib/gitlab/omniauth_initializer.rb @@ -0,0 +1,75 @@ +module Gitlab + class OmniauthInitializer + def initialize(devise_config) + @devise_config = devise_config + end + + def execute(providers) + providers.each do |provider| + add_provider(provider['name'].to_sym, *arguments_for(provider)) + end + end + + private + + def add_provider(*args) + @devise_config.omniauth(*args) + end + + def arguments_for(provider) + provider_arguments = [] + + %w[app_id app_secret].each do |argument| + provider_arguments << provider[argument] if provider[argument] + end + + case provider['args'] + when Array + # An Array from the configuration will be expanded. + provider_arguments.concat provider['args'] + when Hash + hash_arguments = provider['args'].merge(provider_defaults(provider)) + + # A Hash from the configuration will be passed as is. + provider_arguments << hash_arguments.symbolize_keys + end + + provider_arguments + end + + def provider_defaults(provider) + case provider['name'] + when 'cas3' + { on_single_sign_out: cas3_signout_handler } + when 'authentiq' + { remote_sign_out_handler: authentiq_signout_handler } + when 'shibboleth' + { fail_with_empty_uid: true } + else + {} + end + end + + def cas3_signout_handler + lambda do |request| + ticket = request.params[:session_index] + raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket) + + Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket) + true + end + end + + def authentiq_signout_handler + lambda do |request| + authentiq_session = request.params['sid'] + if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session) + Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session) + true + else + false + end + end + end + end +end diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb new file mode 100644 index 00000000000..d808b4d49e0 --- /dev/null +++ b/spec/lib/gitlab/omniauth_initializer_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe Gitlab::OmniauthInitializer do + let(:devise_config) { class_double(Devise) } + + subject { described_class.new(devise_config) } + + describe '#execute' do + it 'configures providers from array' do + generic_config = { 'name' => 'generic' } + + expect(devise_config).to receive(:omniauth).with(:generic) + + subject.execute([generic_config]) + end + + it 'allows "args" array for app_id and app_secret' do + legacy_config = { 'name' => 'legacy', 'args' => %w(123 abc) } + + expect(devise_config).to receive(:omniauth).with(:legacy, '123', 'abc') + + subject.execute([legacy_config]) + end + + it 'passes app_id and app_secret as additional arguments' do + twitter_config = { 'name' => 'twitter', 'app_id' => '123', 'app_secret' => 'abc' } + + expect(devise_config).to receive(:omniauth).with(:twitter, '123', 'abc') + + subject.execute([twitter_config]) + end + + it 'passes "args" hash as symbolized hash argument' do + hash_config = { 'name' => 'hash', 'args' => { 'custom' => 'format' } } + + expect(devise_config).to receive(:omniauth).with(:hash, custom: 'format') + + subject.execute([hash_config]) + end + + it 'configures fail_with_empty_uid for shibboleth' do + shibboleth_config = { 'name' => 'shibboleth', 'args' => {} } + + expect(devise_config).to receive(:omniauth).with(:shibboleth, fail_with_empty_uid: true) + + subject.execute([shibboleth_config]) + end + + it 'configures remote_sign_out_handler proc for authentiq' do + authentiq_config = { 'name' => 'authentiq', 'args' => {} } + + expect(devise_config).to receive(:omniauth).with(:authentiq, remote_sign_out_handler: an_instance_of(Proc)) + + subject.execute([authentiq_config]) + end + + it 'configures on_single_sign_out proc for cas3' do + cas3_config = { 'name' => 'cas3', 'args' => {} } + + expect(devise_config).to receive(:omniauth).with(:cas3, on_single_sign_out: an_instance_of(Proc)) + + subject.execute([cas3_config]) + end + end +end