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
1,834 changes: 920 additions & 914 deletions knapsack_rspec_report.json

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions spec/controllers/accounts_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@
end
end
end

context 'user is not authenticated' do
it 'redirects to sign in page with relevant flash message' do
get :show
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(t('devise.failure.unauthenticated'))
end
end
end

describe '#reauthentication' do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@

expect(response).to redirect_to(phone_setup_url)
end

it 'redirects to authentication if user is fully registered but does not have a phone' do
user = create(:user, :with_authentication_app)
stub_sign_in_before_2fa(user)

get :show, params: { otp_delivery_preference: 'sms' }

expect(response).to redirect_to(user_two_factor_authentication_url)
end
end

describe '#create' do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,27 @@
end
end

context 'with multiple TOTP configurations' do
it 'allows using codes generated from any registered TOTP configuration' do
user = create(:user, :fully_registered)
app1 = Db::AuthAppConfiguration.create(user, user.generate_totp_secret, nil, 'foo')
app2 = Db::AuthAppConfiguration.create(user, user.generate_totp_secret, nil, 'bar')

expect(@analytics).to receive(:track_event).
with('User marked authenticated', authentication_type: :valid_2fa).twice

sign_in_as_user(user)
post :create, params: { code: generate_totp_code(app1.otp_secret_key) }
expect(response).to redirect_to account_url

sign_out(user)

sign_in_as_user(user)
post :create, params: { code: generate_totp_code(app2.otp_secret_key) }
expect(response).to redirect_to account_url
end
end

context 'when the user enters an invalid TOTP' do
before do
sign_in_before_2fa
Expand Down
56 changes: 56 additions & 0 deletions spec/controllers/users/sessions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

RSpec.describe Users::SessionsController, devise: true do
include ActionView::Helpers::DateHelper
include ActionView::Helpers::UrlHelper

let(:mock_valid_site) { 'http://example.com' }

describe 'GET /logout' do
Expand Down Expand Up @@ -302,6 +304,60 @@
expect(response).to render_template(:new)
end

it 'does not allow signing in with empty email' do
post :create, params: { user: { email: '', password: 'foo' } }

expect(flash[:alert]).
to eq t(
'devise.failure.not_found_in_database_html',
link_html: link_to(
t('devise.failure.not_found_in_database_link_text'),
new_user_password_url,
),
)
end

it 'does not allow signing in with the wrong email' do
user = create(:user)
post :create, params: { user: { email: 'invalid@example.com', password: user.password } }

expect(flash[:alert]).
to eq t(
'devise.failure.invalid_html',
link_html: link_to(
t('devise.failure.invalid_link_text'),
new_user_password_url,
),
)
end

it 'does not allow signing in with empty password' do
post :create, params: { user: { email: 'test@example.com', password: '' } }

expect(flash[:alert]).
to eq t(
'devise.failure.not_found_in_database_html',
link_html: link_to(
t('devise.failure.not_found_in_database_link_text'),
new_user_password_url,
),
)
end

it 'does not allow signing in with the wrong password' do
user = create(:user)
post :create, params: { user: { email: user.email, password: 'invalidpass' } }

expect(flash[:alert]).
to eq t(
'devise.failure.invalid_html',
link_html: link_to(
t('devise.failure.invalid_link_text'),
new_user_password_url,
),
)
end

context 'with remember_device cookie present and valid' do
it 'tracks the cookie validity in analytics' do
user = create(:user, :fully_registered)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

RSpec.describe Users::TwoFactorAuthenticationController do
include ActionView::Helpers::DateHelper
include UserAgentHelper

let(:otp_preference_sms) { { otp_delivery_preference: 'sms' } }
let(:user) { create(:user, :fully_registered) }
Expand Down Expand Up @@ -71,16 +72,24 @@ def index
context 'when user is piv/cac enabled' do
it 'renders the piv/cac entry screen' do
allow_any_instance_of(Browser).to receive(:mobile?).and_return(true)
user = build(:user)
user = create(:user, :with_piv_or_cac)
stub_sign_in_before_2fa(user)
allow_any_instance_of(
TwoFactorAuthentication::PivCacPolicy,
).to receive(:enabled?).and_return(true)

get :show

expect(response).to redirect_to login_two_factor_piv_cac_path
end

it 'redirects to phone when on mobile and user has phone' do
allow(controller).to receive(:mobile?).and_return(true)
user = create(:user, :with_phone, :with_piv_or_cac)
stub_sign_in_before_2fa(user)

request.headers['User-Agent'] = mobile_user_agent
get :show

expect(response).to redirect_to login_otp_path(otp_delivery_preference: :sms)
end
end

context 'when user is TOTP enabled' do
Expand Down
134 changes: 0 additions & 134 deletions spec/features/users/sign_in_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,6 @@
to(include(expected_form_action))
end

scenario 'user attempts sign in with a PIV/CAC on mobile' do
allow(BrowserCache).to receive(:parse).and_return(mobile_device)
visit root_path

expect(page).to_not have_link t('account.login.piv_cac')
end

scenario 'user attempts sign in with the default MFA on mobile and a PIV/CAC configured' do
allow(BrowserCache).to receive(:parse).and_return(mobile_device)
sign_in_before_2fa(user_with_piv_cac)

expect(current_path).to eq(login_otp_path(otp_delivery_preference: :sms))
end

scenario 'user attempts sign in with piv/cac with no account then creates account' do
visit_idp_from_sp_with_ial1(:oidc)
click_on t('account.login.piv_cac')
Expand Down Expand Up @@ -249,45 +235,6 @@
end
end

scenario 'user cannot sign in with wrong email' do
user = create(:user)
signin('invalid@email.com', user.password)
link_url = new_user_password_url

expect(page).
to have_link t('devise.failure.invalid_link_text', href: link_url)

email_field = find_field(t('account.index.email'))
expect(email_field.value).to eq('invalid@email.com')
end

scenario 'user cannot sign in with empty email' do
signin('', 'foo')

link_url = new_user_password_url

expect(page).
to have_link t('devise.failure.not_found_in_database_link_text', href: link_url)
end

scenario 'user cannot sign in with empty password' do
signin('test@example.com', '')

link_url = new_user_password_url

expect(page).
to have_link t('devise.failure.not_found_in_database_link_text', href: link_url)
end

scenario 'user cannot sign in with wrong password' do
user = create(:user)
signin(user.email, 'invalidpass')
link_url = new_user_password_url

expect(page).
to have_link t('devise.failure.invalid_link_text', href: link_url)
end

scenario 'user can see and use password visibility toggle', js: true do
visit new_user_session_path

Expand Down Expand Up @@ -446,16 +393,6 @@
end
end

describe 'session timeout configuration' do
it 'uses delay and warning settings whose sum is a multiple of 60' do
expect((session_timeout_start + session_timeout_warning) % 60).to eq 0
end

it 'uses frequency and warning settings whose sum is a multiple of 60' do
expect((session_timeout_frequency + session_timeout_warning) % 60).to eq 0
end
end

context 'user attempts too many concurrent sessions' do
context 'with email and password' do
scenario 'redirects to home page with error' do
Expand Down Expand Up @@ -616,15 +553,6 @@
end
end

context 'visiting a page that requires authentication while signed out' do
it 'redirects to sign in page with relevant flash message' do
visit account_path

expect(current_path).to eq new_user_session_path
expect(page).to have_content(t('devise.failure.unauthenticated'))
end
end

it_behaves_like 'signing in with the site in Spanish', :saml
it_behaves_like 'signing in with the site in Spanish', :oidc

Expand Down Expand Up @@ -795,44 +723,6 @@
end
end

context 'user attempts sign in with bad personal key' do
it 'remains on the login with personal key page' do
user = create(:user, :fully_registered, :with_personal_key)
signin(user.email, user.password)
choose_another_security_option('personal_key')
enter_personal_key(personal_key: 'foo')
click_submit_default

expect(page).to have_current_path(login_two_factor_personal_key_path)
expect(page).to have_content t('two_factor_authentication.invalid_personal_key')
end
end

context 'user is totp_enabled but not phone_enabled' do
before do
user = create(:user, :with_authentication_app, :with_backup_code)
signin(user.email, user.password)
end

it 'requires 2FA before allowing access to phone setup form' do
visit phone_setup_path

expect(page).to have_current_path login_two_factor_authenticator_path
end

it 'does not redirect to phone setup form when visiting /login/two_factor/sms' do
visit login_two_factor_path(otp_delivery_preference: 'sms')

expect(page).to have_current_path login_two_factor_authenticator_path
end

it 'does not redirect to phone setup form when visiting /login/two_factor/voice' do
visit login_two_factor_path(otp_delivery_preference: 'voice')

expect(page).to have_current_path login_two_factor_authenticator_path
end
end

context 'visiting via SP1, then via SP2, then signing in' do
it 'redirects to SP2' do
user = create(:user, :fully_registered)
Expand Down Expand Up @@ -886,30 +776,6 @@
end
end

context 'multiple auth apps' do
it 'allows you to sign in with either' do
user = create(:user, :fully_registered)
Db::AuthAppConfiguration.create(user, 'foo', nil, 'foo')
Db::AuthAppConfiguration.create(user, 'bar', nil, 'bar')

visit new_user_session_path
fill_in_credentials_and_submit(user.email, user.password)
fill_in :code, with: generate_totp_code('foo')
click_submit_default

expect(current_url).to eq account_url

Capybara.reset_session!

visit new_user_session_path
fill_in_credentials_and_submit(user.email, user.password)
fill_in :code, with: generate_totp_code('bar')
click_submit_default

expect(current_url).to eq account_url
end
end

context 'oidc sp requests ialmax' do
context 'the service_provider is on the allow list' do
before do
Expand Down
10 changes: 10 additions & 0 deletions spec/helpers/session_timeout_warning_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,14 @@
end
end
end

describe 'session timeout configuration' do
it 'uses delay and warning settings whose sum is a multiple of 60' do
expect((session_timeout_start + session_timeout_warning) % 60).to eq 0
end

it 'uses frequency and warning settings whose sum is a multiple of 60' do
expect((session_timeout_frequency + session_timeout_warning) % 60).to eq 0
end
end
end
7 changes: 3 additions & 4 deletions spec/support/features/doc_auth_helper.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require_relative 'document_capture_step_helper'
require_relative 'interaction_helper'
require_relative '../user_agent_helper'

module DocAuthHelper
include InteractionHelper
include DocumentCaptureStepHelper
include UserAgentHelper

GOOD_SSN = Idp::Constants::MOCK_IDV_APPLICANT_WITH_SSN[:ssn]
GOOD_SSN_MASKED = '9**-**-***4'
Expand Down Expand Up @@ -111,10 +113,7 @@ def complete_doc_auth_steps_before_phone_otp_step(expect_accessible: false)
end

def mobile_device
Browser.new(
'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) \
AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
)
Browser.new(mobile_user_agent)
end

def complete_doc_auth_steps_before_ssn_step(expect_accessible: false)
Expand Down
6 changes: 6 additions & 0 deletions spec/support/user_agent_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module UserAgentHelper
def mobile_user_agent
'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) \
AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
end
end
Loading