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
2 changes: 1 addition & 1 deletion config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ reg_unconfirmed_email_max_attempts: 20
reg_unconfirmed_email_window_in_minutes: 60
reject_id_token_hint_in_logout: false
remember_device_expiration_hours_aal_1: 720
remember_device_expiration_hours_aal_2: 12
remember_device_expiration_hours_aal_2: 0
report_timeout: 0
requests_per_ip_cidr_allowlist: ''
requests_per_ip_limit: 300
Expand Down
14 changes: 14 additions & 0 deletions config/service_providers.localdev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,20 @@ test:
ial: 2
allow_prompt_login: true

'urn:gov:gsa:openidconnect:sp:server_ial1':
agency_id: 2
redirect_uris:
- 'http://localhost:7654/auth/result'
- 'https://example.com'
- 'http://www.example.com/test/oidc'
certs:
- 'saml_test_sp'
friendly_name: 'Test SP'
return_to_sp_url: 'https://example.com/'
assertion_consumer_logout_service_url: ''
ial: 1
allow_prompt_login: true

'urn:gov:gsa:openidconnect:sp:server_two':
agency_id: 2
redirect_uris:
Expand Down
14 changes: 7 additions & 7 deletions spec/controllers/saml_idp_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ def name_id_version(format_urn)
end

let(:xmldoc) { SamlResponseDoc.new('controller', 'response_assertion', response) }
let(:aal_level) { 2 }
let(:aal_level) { 0 }
let(:ial2_settings) do
saml_settings(
overrides: {
Expand Down Expand Up @@ -934,7 +934,7 @@ def name_id_version(format_urn)
with('SAML Auth Request', {
requested_ial: Saml::Idp::Constants::IAL1_AUTHN_CONTEXT_CLASSREF,
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: true,
})

Expand Down Expand Up @@ -1564,7 +1564,7 @@ def name_id_version(format_urn)
with('SAML Auth Request', {
requested_ial: Saml::Idp::Constants::IAL1_AUTHN_CONTEXT_CLASSREF,
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: false,
})

Expand Down Expand Up @@ -1931,8 +1931,8 @@ def name_id_version(format_urn)
expect(subject).to_not be_nil
end

it 'has contents set to AAL2' do
expect(subject.content).to eq Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF
it 'has contents set to default AAL' do
expect(subject.content).to eq Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF
end
end
end
Expand Down Expand Up @@ -2056,7 +2056,7 @@ def stub_requested_attributes
with('SAML Auth Request', {
requested_ial: Saml::Idp::Constants::IAL1_AUTHN_CONTEXT_CLASSREF,
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: false,
})
expect(@analytics).to receive(:track_event).with('SAML Auth', analytics_hash)
Expand Down Expand Up @@ -2094,7 +2094,7 @@ def stub_requested_attributes
with('SAML Auth Request', {
requested_ial: Saml::Idp::Constants::IAL1_AUTHN_CONTEXT_CLASSREF,
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: false,
})
expect(@analytics).to receive(:track_event).with('SAML Auth', analytics_hash)
Expand Down
4 changes: 2 additions & 2 deletions spec/decorators/service_provider_session_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@
allow(sp).to receive(:default_aal).and_return(2)
end

it { expect(subject.mfa_expiration_interval).to eq(12.hours) }
it { expect(subject.mfa_expiration_interval).to eq(0.hours) }
end

context 'with an IAL2 sp' do
before do
allow(sp).to receive(:ial).and_return(2)
end

it { expect(subject.mfa_expiration_interval).to eq(12.hours) }
it { expect(subject.mfa_expiration_interval).to eq(0.hours) }
end

context 'with an sp that is not AAL2 or IAL2' do
Expand Down
2 changes: 1 addition & 1 deletion spec/features/idv/doc_auth/verify_info_step_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
context 'when the SP is in the AAMVA banlist' do
it 'does not perform the state ID check' do
allow(IdentityConfig.store).to receive(:aamva_sp_banlist_issuers).
and_return('["urn:gov:gsa:openidconnect:sp:server"]')
and_return("[\"#{OidcAuthHelper::OIDC_IAL1_ISSUER}\"]")
user = create(:user, :fully_registered)
expect_any_instance_of(Idv::Agent).
to receive(:proof_resolution).
Expand Down
2 changes: 1 addition & 1 deletion spec/features/openid_connect/openid_connect_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
visit_idp_from_ial1_oidc_sp

cookie = cookies.find { |c| c.name == 'sp_issuer' }.value
expect(cookie).to eq(OidcAuthHelper::OIDC_ISSUER)
expect(cookie).to eq(OidcAuthHelper::OIDC_IAL1_ISSUER)
end

it 'receives an ID token with a kid that matches the certs endpooint' do
Expand Down
2 changes: 1 addition & 1 deletion spec/features/remember_device/session_expiration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
first(:link, t('links.sign_out')).click

IdentityLinker.new(
user, build(:service_provider, issuer: 'urn:gov:gsa:openidconnect:sp:server')
user, build(:service_provider, issuer: OidcAuthHelper::OIDC_IAL1_ISSUER)
).link_identity(verified_attributes: %w[email])

visit_idp_from_sp_with_ial1(:oidc)
Expand Down
122 changes: 67 additions & 55 deletions spec/features/remember_device/sp_expiration_spec.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
require 'rails_helper'

RSpec.shared_examples 'expiring remember device for an sp config' do |expiration_time, protocol|
# rubocop:disable Layout/LineLength
RSpec.shared_examples 'expiring remember device for an sp config' do |expiration_time, protocol, aal|
# rubocop:enable Layout/LineLength
before do
user # Go through the signup flow and remember user before visiting SP
end

def visit_sp(protocol, aal)
if aal == 2
visit_idp_from_sp_with_ial1_aal2(protocol)
else
visit_idp_from_sp_with_ial1(protocol)
end
end

context "#{protocol}: signing in" do
it "does not require MFA before #{expiration_time.inspect}" do
travel_to(expiration_time.from_now - 1.day) do
visit_idp_from_sp_with_ial1(protocol)
visit_sp(protocol, aal)
sign_in_user(user)
click_submit_default if protocol == :saml
expect(page).to have_current_path(sign_up_completed_path)
Expand All @@ -17,22 +27,7 @@

it "does require MFA after #{expiration_time.inspect}" do
travel_to(expiration_time.from_now + 1.day) do
visit_idp_from_sp_with_ial1(protocol)
sign_in_user(user)

expect(page).to have_content(t('two_factor_authentication.header_text'))
expect(current_path).to eq(login_two_factor_path(otp_delivery_preference: :sms))

fill_in_code_with_last_phone_otp
protocol == :saml ? click_submit_default_twice : click_submit_default

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

it 'requires MFA when AAL2 request is sent after 12 hours' do
travel_to(12.hours.from_now + 1.day) do
visit_idp_from_sp_with_ial1_aal2(protocol)
visit_sp(protocol, aal)
sign_in_user(user)

expect(page).to have_content(t('two_factor_authentication.header_text'))
Expand All @@ -44,57 +39,56 @@
expect(page).to have_current_path(sign_up_completed_path)
end
end
end

context "#{protocol}: visiting while already signed in" do
it "does not require MFA before #{expiration_time.inspect}" do
travel_to(expiration_time.from_now - 1.day) do
sign_in_user(user)
visit_idp_from_sp_with_ial1(protocol)
context "#{protocol}: visiting while already signed in" do
it "does not require MFA before #{expiration_time.inspect}" do
travel_to(expiration_time.from_now - 1.day) do
sign_in_user(user)
visit_sp(protocol, aal)

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

it "does require MFA after #{expiration_time.inspect}" do
travel_to(expiration_time.from_now + 1.day) do
if expiration_time == 30.days
sign_in_live_with_2fa(user)
visit_idp_from_sp_with_ial1(protocol)
else
it "does require MFA after #{expiration_time.inspect}" do
travel_to(expiration_time.from_now + 1.day) do
sign_in_user(user)
visit_idp_from_sp_with_ial1(protocol)
visit_sp(protocol, aal)

expect(page).to have_content(t('two_factor_authentication.header_text'))
expect(current_path).to eq(login_two_factor_path(otp_delivery_preference: :sms))
expect(page).to have_content(t('two_factor_authentication.header_text'))

fill_in_code_with_last_phone_otp
protocol == :saml ? click_submit_default_twice : click_submit_default
end

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

it 'does require MFA when AAL2 request is sent after 12 hours' do
travel_to(12.hours.from_now + 1.day) do
visit_idp_from_sp_with_ial1_aal2(protocol)
sign_in_user(user)
it 'does require MFA when AAL2 request is sent after configured AAL2 timeframe' do
travel_to(AAL2_REMEMBER_DEVICE_EXPIRATION.from_now + 1.day) do
visit_idp_from_sp_with_ial1_aal2(protocol)
sign_in_user(user)

expect(page).to have_content(t('two_factor_authentication.header_text'))
expect(current_path).to eq(login_two_factor_path(otp_delivery_preference: :sms))
expect(page).to have_content(t('two_factor_authentication.header_text'))
expect(current_path).to eq(login_two_factor_path(otp_delivery_preference: :sms))

fill_in_code_with_last_phone_otp
protocol == :saml ? click_submit_default_twice : click_submit_default
fill_in_code_with_last_phone_otp
protocol == :saml ? click_submit_default_twice : click_submit_default

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

RSpec.feature 'remember device sp expiration' do
include SamlAuthHelper
AAL1_REMEMBER_DEVICE_EXPIRATION =
IdentityConfig.store.remember_device_expiration_hours_aal_1.hours
AAL2_REMEMBER_DEVICE_EXPIRATION =
IdentityConfig.store.remember_device_expiration_hours_aal_2.hours

let(:user) do
user_record = sign_up_and_set_password
Expand All @@ -115,7 +109,7 @@
before do
allow(IdentityConfig.store).to receive(:otp_delivery_blocklist_maxretry).and_return(1000)

ServiceProvider.find_by(issuer: 'urn:gov:gsa:openidconnect:sp:server').update!(
ServiceProvider.find_by(issuer: OidcAuthHelper::OIDC_IAL1_ISSUER).update!(
default_aal: aal,
ial: ial,
)
Expand All @@ -130,32 +124,50 @@
let(:aal) { 2 }
let(:ial) { 1 }

it_behaves_like 'expiring remember device for an sp config', 12.hours, :oidc
it_behaves_like 'expiring remember device for an sp config', 12.hours, :saml
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:oidc
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:saml
end

context 'with an IAL2 SP' do
let(:aal) { 1 }
let(:ial) { 2 }

it_behaves_like 'expiring remember device for an sp config', 12.hours, :oidc
it_behaves_like 'expiring remember device for an sp config', 12.hours, :saml
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:oidc
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:saml
end

context 'with an AAL2 and IAL2 SP' do
let(:aal) { 2 }
let(:ial) { 2 }

it_behaves_like 'expiring remember device for an sp config', 12.hours, :oidc
it_behaves_like 'expiring remember device for an sp config', 12.hours, :saml
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:oidc
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:saml
end

context 'with an AAL1 and IAL1 SP' do
let(:aal) { 1 }
let(:ial) { 1 }

it_behaves_like 'expiring remember device for an sp config', 30.days, :oidc
it_behaves_like 'expiring remember device for an sp config', 30.days, :saml
it_behaves_like 'expiring remember device for an sp config', AAL1_REMEMBER_DEVICE_EXPIRATION,
:oidc
it_behaves_like 'expiring remember device for an sp config', AAL1_REMEMBER_DEVICE_EXPIRATION,
:saml
end

context 'with an AAL1 and IAL1 SP requesting AAL2' do
let(:aal) { 1 }
let(:ial) { 1 }

it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:oidc, 2
it_behaves_like 'expiring remember device for an sp config', AAL2_REMEMBER_DEVICE_EXPIRATION,
:saml, 2
end
end
end
2 changes: 1 addition & 1 deletion spec/features/reports/sp_active_users_report_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
click_agree_and_continue
expect(current_url).to start_with('http://localhost:7654/auth/result')

results = [{ issuer: 'urn:gov:gsa:openidconnect:sp:server',
results = [{ issuer: OidcAuthHelper::OIDC_IAL1_ISSUER,
app_id: nil,
total_ial1_active: 1,
total_ial2_active: 0 }].to_json
Expand Down
5 changes: 3 additions & 2 deletions spec/features/saml/saml_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@

# log in for second time
fill_in_credentials_and_submit(user.email, user.password)
fill_in_code_with_last_phone_otp
click_submit_default_twice

xmldoc = SamlResponseDoc.new('feature', 'response_assertion')
Expand Down Expand Up @@ -408,7 +409,7 @@
expect(fake_analytics.events['SAML Auth Request']).to eq(
[{ requested_ial: 'http://idmanagement.gov/ns/assurance/ial/1',
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: false }],
)
expect(fake_analytics.events['SAML Auth'].count).to eq 2
Expand Down Expand Up @@ -467,7 +468,7 @@
expect(fake_analytics.events['SAML Auth Request']).to eq(
[{ requested_ial: 'http://idmanagement.gov/ns/assurance/ial/1',
service_provider: 'http://localhost:3000',
requested_aal_authn_context: Saml::Idp::Constants::AAL2_AUTHN_CONTEXT_CLASSREF,
requested_aal_authn_context: Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF,
force_authn: false }],
)
expect(fake_analytics.events['SAML Auth'].count).to eq 2
Expand Down
3 changes: 2 additions & 1 deletion spec/features/sign_in/banned_users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

RSpec.feature 'Banning users for an SP' do
include SamlAuthHelper
include OidcAuthHelper

context 'a user is banned from all SPs' do
it 'does not let the user sign in to any SP' do
Expand Down Expand Up @@ -45,7 +46,7 @@
it 'bans the user from signing in to the banned SP but allows other sign ins' do
user = create(:user, :fully_registered)

SignInRestriction.create(user: user, service_provider: 'urn:gov:gsa:openidconnect:sp:server')
SignInRestriction.create(user: user, service_provider: OidcAuthHelper::OIDC_IAL1_ISSUER)

sign_in_live_with_2fa(user)
expect(current_path).to eq(account_path)
Expand Down
2 changes: 1 addition & 1 deletion spec/features/sign_in/remember_device_default_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

it 'does not have remember device checked' do
user = create(:user, :fully_registered)
visit_idp_from_sp_with_ial1(:oidc)
visit_idp_from_sp_with_ial1_aal2(:oidc)
fill_in_credentials_and_submit(user.email, user.password)
expect(page).to_not have_checked_field t('forms.messages.remember_device')
end
Expand Down
Loading