Skip to content
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
9 changes: 6 additions & 3 deletions app/presenters/two_factor_login_options_presenter.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
class TwoFactorLoginOptionsPresenter < TwoFactorAuthCode::GenericDeliveryPresenter
include ActionView::Helpers::TranslationHelper

attr_reader :user, :phishing_resistant_required, :piv_cac_required
attr_reader :user, :reauthentication_context, :phishing_resistant_required, :piv_cac_required

alias_method :reauthentication_context?, :reauthentication_context
alias_method :phishing_resistant_required?, :phishing_resistant_required
alias_method :piv_cac_required?, :piv_cac_required

Expand Down Expand Up @@ -35,6 +36,8 @@ def info
end

def restricted_options_warning_text
return if reauthentication_context?

if piv_cac_required?
t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name:)
elsif phishing_resistant_required?
Expand All @@ -46,9 +49,9 @@ def options
return @options if defined?(@options)
mfa = MfaContext.new(user)

if @piv_cac_required
if piv_cac_required? && !reauthentication_context?
configurations = mfa.piv_cac_configurations
elsif @phishing_resistant_required
elsif phishing_resistant_required? && !reauthentication_context?
configurations = mfa.phishing_resistant_configurations
else
configurations = mfa.two_factor_configurations
Expand Down
93 changes: 54 additions & 39 deletions spec/features/openid_connect/phishing_resistant_required_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,60 @@

RSpec.describe 'Phishing-resistant authentication required in an OIDC context' do
include OidcAuthHelper
include WebAuthnHelper

describe 'OpenID Connect requesting AAL3 authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
user = user_with_2fa
shared_examples 'setting up phishing-resistant authenticator in an OIDC context' do
it 'sends user to set up phishing-resistant auth' do
sign_in_live_with_2fa(user)

visit_idp_from_ial1_oidc_sp_requesting_aal3(prompt: 'select_account')
sign_in_live_with_2fa(user)
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")

# Validate that user is not allowed to continue without making a selection.
click_continue
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('errors.two_factor_auth_setup.must_select_option'))

# Regression (LG-11110): Ensure the user can reauthenticate with any existing configuration,
# not limited based on phishing-resistant requirement.
travel (IdentityConfig.store.reauthn_window + 1).seconds do
check t('two_factor_authentication.two_factor_choice_options.webauthn')
click_continue

expect(page).to have_content(t('two_factor_authentication.login_options.sms'))
expect(page).to have_content(t('two_factor_authentication.login_options.voice'))

choose t('two_factor_authentication.login_options.sms')
click_continue

expect(current_url).to eq(authentication_methods_setup_url)
fill_in_code_with_last_phone_otp
click_submit_default

# LG-11193: Currently the user is redirected back to the MFA setup selection after
# reauthenticating. This should be improved to remember their original selection.
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
mock_webauthn_setup_challenge
check t('two_factor_authentication.two_factor_choice_options.webauthn')
click_continue

fill_in_nickname_and_click_continue
mock_press_button_on_hardware_key_on_setup

expect(page).to have_current_path(sign_up_completed_path)
end
end
end

describe 'OpenID Connect requesting AAL3 authentication' do
context 'user does not have phishing-resistant auth configured' do
let(:user) { create(:user, :fully_registered, :with_phone) }

before { visit_idp_from_ial1_oidc_sp_requesting_aal3(prompt: 'select_account') }

it_behaves_like 'setting up phishing-resistant authenticator in an OIDC context'
end

context 'user has phishing-resistant auth configured' do
context 'with piv cac configured' do
Expand Down Expand Up @@ -65,16 +105,11 @@

describe 'OpenID Connect requesting phishing-resistant authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
user = user_with_2fa
let(:user) { create(:user, :fully_registered, :with_phone) }

visit_idp_from_ial1_oidc_sp_requesting_phishing_resistant(prompt: 'select_account')
sign_in_live_with_2fa(user)
before { visit_idp_from_ial1_oidc_sp_requesting_phishing_resistant(prompt: 'select_account') }

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
end
it_behaves_like 'setting up phishing-resistant authenticator in an OIDC context'
end

context 'user has phishing-resistant auth configured' do
Expand Down Expand Up @@ -125,31 +160,11 @@

describe 'ServiceProvider configured to default to AAL3 authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
user = user_with_2fa
let(:user) { create(:user, :fully_registered, :with_phone) }

visit_idp_from_ial1_oidc_sp_defaulting_to_aal3(prompt: 'select_account')
sign_in_live_with_2fa(user)

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
end
before { visit_idp_from_ial1_oidc_sp_defaulting_to_aal3(prompt: 'select_account') }

it 'throws an error if user doesnt select phishing-resistant auth' do
user = user_with_2fa

visit_idp_from_ial1_oidc_sp_defaulting_to_aal3(prompt: 'select_account')
sign_in_live_with_2fa(user)

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")

click_continue

expect(page).to have_content(t('errors.two_factor_auth_setup.must_select_option'))
end
it_behaves_like 'setting up phishing-resistant authenticator in an OIDC context'
end

context 'user has phishing-resistant auth configured' do
Expand Down
79 changes: 61 additions & 18 deletions spec/features/saml/phishing_resistant_required_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,65 @@

RSpec.describe 'Phishing-resistant authentication required in an SAML context' do
include SamlAuthHelper
include WebAuthnHelper

shared_examples 'setting up phishing-resistant authenticator in an SAML context' do
it 'sends user to set up phishing-resistant auth' do
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")

# Validate that user is not allowed to continue without making a selection.
click_continue
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('errors.two_factor_auth_setup.must_select_option'))

# Regression (LG-11110): Ensure the user can reauthenticate with any existing configuration,
# not limited based on phishing-resistant requirement.
travel (IdentityConfig.store.reauthn_window + 1).seconds do
check t('two_factor_authentication.two_factor_choice_options.webauthn')
click_continue

expect(page).to have_content(t('two_factor_authentication.login_options.sms'))
expect(page).to have_content(t('two_factor_authentication.login_options.voice'))

choose t('two_factor_authentication.login_options.sms')
click_continue

fill_in_code_with_last_phone_otp
click_submit_default

# LG-11193: Currently the user is redirected back to the MFA setup selection after
# reauthenticating. This should be improved to remember their original selection.
expect(page).to have_current_path(authentication_methods_setup_path)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
mock_webauthn_setup_challenge
check t('two_factor_authentication.two_factor_choice_options.webauthn')
click_continue

fill_in_nickname_and_click_continue
mock_press_button_on_hardware_key_on_setup

expect(page).to have_current_path(sign_up_completed_path)
end
end
end

describe 'SAML ServiceProvider requesting phishing-resistant authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
sign_in_and_2fa_user(user_with_2fa)
let(:user) { create(:user, :proofed, :with_phone) }

before do
sign_in_and_2fa_user(user)
visit_saml_authn_request_url(
overrides: {
issuer: sp1_issuer,
authn_context: Saml::Idp::Constants::AAL2_PHISHING_RESISTANT_AUTHN_CONTEXT_CLASSREF,
},
)

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
end

it_behaves_like 'setting up phishing-resistant authenticator in an SAML context'
end

context 'user has phishing-resistant auth configured' do
Expand Down Expand Up @@ -76,18 +119,18 @@

describe 'SAML ServiceProvider requesting AAL3 authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
sign_in_and_2fa_user(user_with_2fa)
let(:user) { create(:user, :proofed, :with_phone) }

before do
sign_in_and_2fa_user(user)
visit_saml_authn_request_url(
overrides: {
issuer: sp1_issuer, authn_context: Saml::Idp::Constants::AAL3_AUTHN_CONTEXT_CLASSREF
},
)

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
end

it_behaves_like 'setting up phishing-resistant authenticator in an SAML context'
end

context 'user has phishing-resistant auth configured' do
Expand Down Expand Up @@ -143,18 +186,18 @@

describe 'SAML ServiceProvider configured to default to AAL3 authentication' do
context 'user does not have phishing-resistant auth configured' do
it 'sends user to set up phishing-resistant auth' do
sign_in_and_2fa_user(user_with_2fa)
let(:user) { create(:user, :proofed, :with_phone) }

before do
sign_in_and_2fa_user(user)
visit_saml_authn_request_url(
overrides: {
issuer: aal3_issuer, authn_context: nil
},
)

expect(current_url).to eq(authentication_methods_setup_url)
expect(page).to have_content(t('two_factor_authentication.two_factor_aal3_choice'))
expect(page).to have_xpath("//img[@alt='important alert icon']")
end

it_behaves_like 'setting up phishing-resistant authenticator in an SAML context'
end

context 'user has phishing-resistant auth configured' do
Expand Down
Loading