diff --git a/app/controllers/concerns/enforces_step_up_authentication_for_namespace.rb b/app/controllers/concerns/enforces_step_up_authentication_for_namespace.rb index 101a2b685ba4f41c4a6bceedc14d2b3f57485a39..ebcf99b18f01a5dc3f62fefdccdffe443bb37f56 100644 --- a/app/controllers/concerns/enforces_step_up_authentication_for_namespace.rb +++ b/app/controllers/concerns/enforces_step_up_authentication_for_namespace.rb @@ -44,7 +44,7 @@ def enforce_step_up_auth_for(namespace) return unless step_up_auth_supported_for_namespace?(namespace) return unless step_up_auth_required_for_namespace?(namespace) - return if step_up_auth_succeeded_for_namespace? + return if step_up_auth_succeeded_for_namespace?(namespace) handle_failed_step_up_auth_for_namespace(namespace) end @@ -66,11 +66,17 @@ def step_up_auth_required_for_namespace?(namespace) ) end - def step_up_auth_succeeded_for_namespace? - ::Gitlab::Auth::Oidc::StepUpAuthentication.succeeded?( - session, - scope: ::Gitlab::Auth::Oidc::StepUpAuthentication::SCOPE_NAMESPACE - ) + def step_up_auth_succeeded_for_namespace?(namespace) + provider_name = namespace.step_up_auth_required_oauth_provider_from_self_or_inherited + return false unless provider_name + + ::Gitlab::Auth::Oidc::StepUpAuthentication + .build_flow( + provider: provider_name, + session: session, + scope: ::Gitlab::Auth::Oidc::StepUpAuthentication::SCOPE_NAMESPACE + ) + .succeeded? end def handle_failed_step_up_auth_for_namespace(namespace) diff --git a/spec/support/shared_examples/enforce_step_up_auth_shared_examples.rb b/spec/support/shared_examples/enforce_step_up_auth_shared_examples.rb index 7176ea50982fc226f3cb7d9ca0eedc9267c1a946..b5cbbe3e235d5ef602a43a7fa6e1ffe82cd99001 100644 --- a/spec/support/shared_examples/enforce_step_up_auth_shared_examples.rb +++ b/spec/support/shared_examples/enforce_step_up_auth_shared_examples.rb @@ -162,6 +162,77 @@ end end end + + context 'with multiple OAuth providers configured' do + let(:provider_without_step_up) do + GitlabSettings::Options.new(name: 'github') + end + + let(:another_step_up_provider) do + GitlabSettings::Options.new( + name: 'saml', + step_up_auth: { + namespace: { + id_token: { + required: { acr: 'silver' } + } + } + } + ) + end + + before do + # Configure multiple providers + stub_omniauth_setting( + enabled: true, + providers: [oidc_provider_config, provider_without_step_up, another_step_up_provider] + ) + allow(Devise).to receive(:omniauth_providers).and_return( + [oidc_provider_name, provider_without_step_up.name, another_step_up_provider.name] + ) + end + + context 'when group requires specific step-up auth provider' do + before do + group.namespace_settings.update!(step_up_auth_required_oauth_provider: oidc_provider_name) + end + + context 'when user has succeeded with a different step-up provider' do + let(:session_data) do + { + 'omniauth_step_up_auth' => { + another_step_up_provider.name => { 'namespace' => { 'state' => 'succeeded' } } + } + } + end + + it 'still requires step-up auth with the configured provider' do + subject + + # User has step-up auth succeeded with 'saml' but group requires 'openid_connect' + expect(response).to redirect_to(new_group_step_up_auth_path(group)) + expect(response).to have_gitlab_http_status(:found) + end + end + + context 'when user has succeeded with the correct provider' do + let(:session_data) do + { + 'omniauth_step_up_auth' => { + oidc_provider_name => { 'namespace' => { 'state' => 'succeeded' } } + } + } + end + + it 'allows access with matching provider session' do + subject + + expect(response).to have_gitlab_http_status(expected_success_status) + expect(response).not_to redirect_to(new_group_step_up_auth_path(group)) + end + end + end + end end RSpec.shared_examples 'enforces step-up authentication (request spec)' do