Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
19d4cfd
update
mdiarra3 Jun 15, 2022
5fc2504
add addiitonal required controller
mdiarra3 Jun 15, 2022
07a2f2e
required
mdiarra3 Jun 15, 2022
4ef3a9d
LG-6527: prelogic kantara
mdiarra3 Jun 17, 2022
6ac88d2
Merge remote-tracking branch 'origin/main' into LG-6527-pre-logic-ann…
mdiarra3 Jun 17, 2022
223e57a
LG-6527: updated prelogic for kantara req
mdiarra3 Jun 21, 2022
38b60ea
Merge remote-tracking branch 'origin/main' into LG-6527-pre-logic-ann…
mdiarra3 Jun 22, 2022
27603e3
prelogic fix
mdiarra3 Jun 22, 2022
547421a
LG-6527: allow users to skip with a migration
mdiarra3 Jun 23, 2022
a3617aa
presenter test and updated language
mdiarra3 Jun 27, 2022
2f99d7a
changelog: Upcoming Features, Authentication, add more forgiving meth…
mdiarra3 Jun 27, 2022
4d60e1b
LG-6527: update timestamp, add feature tests
mdiarra3 Jun 28, 2022
3b0015a
Merge remote-tracking branch 'origin/main' into LG-6527-pre-logic-ann…
mdiarra3 Jun 28, 2022
162a30c
LG-6527: update specs
mdiarra3 Jun 28, 2022
3d40d1a
LG-6527: update spec
mdiarra3 Jun 28, 2022
614416c
Lg-6527: update config to move to applciation controller
mdiarra3 Jun 29, 2022
f9993f0
update and fix tests
mdiarra3 Jun 29, 2022
a325174
remove dupe method
mdiarra3 Jun 29, 2022
ba61bd1
remove whitespace
mdiarra3 Jun 29, 2022
7344a29
capitalize the A
mdiarra3 Jul 1, 2022
2c0b084
update event comment
mdiarra3 Jul 1, 2022
5c3e299
Merge remote-tracking branch 'origin/main' into LG-6527-pre-logic-ann…
mdiarra3 Jul 1, 2022
06fb964
LG-6527: default set to true
mdiarra3 Jul 1, 2022
cfae06f
update tests
mdiarra3 Jul 1, 2022
9ea111d
update schema
mdiarra3 Jul 6, 2022
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
11 changes: 6 additions & 5 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ def user_fully_authenticated?
end

def two_factor_kantara_enabled?
return false if controller_path == 'mfa_confirmation'
return false if controller_path == 'additional_mfa_required'
return false if user_session[:skip_kantara_req]
IdentityConfig.store.kantara_2fa_phone_existing_user_restriction &&
MfaContext.new(current_user).enabled_non_restricted_mfa_methods_count < 1
end
Expand Down Expand Up @@ -338,10 +339,6 @@ def prompt_to_setup_mfa
redirect_to authentication_methods_setup_url
end

def prompt_to_setup_non_restricted_mfa
redirect_to auth_method_confirmation_url
end

def prompt_to_verify_mfa
redirect_to user_two_factor_authentication_url
end
Expand All @@ -350,6 +347,10 @@ def prompt_to_verify_sp_required_mfa
redirect_to sp_required_mfa_verification_url
end

def prompt_to_setup_non_restricted_mfa
redirect_to login_additional_mfa_required_url
end

def sp_required_mfa_verification_url
return login_two_factor_piv_cac_url if service_provider_mfa_policy.piv_cac_required?

Expand Down
13 changes: 2 additions & 11 deletions app/controllers/mfa_confirmation_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ class MfaConfirmationController < ApplicationController

def show
@content = MfaConfirmationPresenter.new(current_user)
@next_path = next_path
analytics.user_registration_suggest_another_mfa_notice_visited
end

def skip
user_session.delete(:mfa_selections)
user_session.delete(:next_mfa_selection_choice)
analytics.user_registration_suggest_another_mfa_notice_skipped
redirect_to after_mfa_setup_path
end

Expand All @@ -27,16 +28,6 @@ def create

private

def enforce_second_mfa?
IdentityConfig.store.kantara_2fa_phone_restricted &&
MfaContext.new(current_user).enabled_non_restricted_mfa_methods_count < 1
end

def next_path
return second_mfa_setup_non_restricted_path if enforce_second_mfa?
second_mfa_setup_path
end

def password
params.require(:user)[:password]
end
Expand Down
28 changes: 28 additions & 0 deletions app/controllers/users/additional_mfa_required_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Users
class AdditionalMfaRequiredController < ApplicationController
extend ActiveSupport::Concern

def show
@content = AdditionalMfaRequiredPresenter.new(current_user: current_user)
analytics.non_restricted_mfa_required_prompt_visited
end

def skip
user_session[:skip_kantara_req] = true
if Time.zone.today > enforcement_date
UpdateUser.new(
user: current_user,
attributes: { non_restricted_mfa_required_prompt_skip_date: Time.zone.today },
).call
end
analytics.non_restricted_mfa_required_prompt_skipped
redirect_to after_sign_in_path_for(current_user)
end

private

def enforcement_date
@enforcement_date ||= IdentityConfig.store.kantara_restriction_enforcement_date
end
end
end
8 changes: 1 addition & 7 deletions app/controllers/users/mfa_selection_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class MfaSelectionController < ApplicationController
include MfaSetupConcern

before_action :authenticate_user
before_action :confirm_user_authenticated_for_2fa_setup, except: :non_restricted
before_action :confirm_user_authenticated_for_2fa_setup
before_action :multiple_factors_enabled?

def index
Expand All @@ -14,12 +14,6 @@ def index
analytics.user_registration_2fa_additional_setup_visit
end

def non_restricted
@two_factor_options_form = TwoFactorOptionsForm.new(current_user)
@presenter = two_factor_options_presenter
render 'index'
end

def update
result = submit_form
analytics.user_registration_2fa_additional_setup(**result.to_h)
Expand Down
68 changes: 68 additions & 0 deletions app/presenters/additional_mfa_required_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
class AdditionalMfaRequiredPresenter
attr_reader :current_user
def initialize(current_user:)
@current_user = current_user
end

def title
if current_date > enforcement_date
I18n.t('mfa.additional_mfa_required.heading')
else
I18n.t(
'mfa.additional_mfa_required.title',
date: I18n.l(enforcement_date, format: :event_date),
)
end
end

def button
I18n.t('mfa.additional_mfa_required.button')
end

def info
if current_date > enforcement_date
I18n.t('mfa.additional_mfa_required.non_restricted_required_info')
else
I18n.t(
'mfa.additional_mfa_required.info',
date: I18n.l(enforcement_date, format: :event_date),
)
end
end

def skip
if current_date > enforcement_date
I18n.t('mfa.skip_once')
else
I18n.t('mfa.skip')
end
end

def learn_more_text
I18n.t('mfa.additional_mfa_required.learn_more')
end

def cant_skip_anymore?
return false if current_date < enforcement_date
return false unless current_user.non_restricted_mfa_required_prompt_skip_date
current_user.non_restricted_mfa_required_prompt_skip_date >
enforcement_date
end

def learn_more_link
MarketingSite.help_center_article_url(
category: 'get-started',
article: 'authentication-options',
)
end

private

def current_date
@current_date ||= Time.zone.today
end

def enforcement_date
@enforcement_date ||= IdentityConfig.store.kantara_restriction_enforcement_date
end
end
22 changes: 3 additions & 19 deletions app/presenters/mfa_confirmation_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,15 @@ def initialize(user)
@user = user
end

def enforce_second_mfa?
IdentityConfig.store.select_multiple_mfa_options &&
MfaContext.new(@user).enabled_non_restricted_mfa_methods_count < 1
end

def heading
enforce_second_mfa? ?
I18n.t('mfa.non_restricted.heading') :
I18n.t('titles.mfa_setup.suggest_second_mfa')
I18n.t('titles.mfa_setup.suggest_second_mfa')
end

def info
enforce_second_mfa? ? I18n.t(
'mfa.non_restricted.info',
) : I18n.t('mfa.account_info')
I18n.t('mfa.account_info')
end

def button
enforce_second_mfa? ? I18n.t('mfa.non_restricted.button') : I18n.t('mfa.add')
end

def learn_more
MarketingSite.help_center_article_url(
category: 'get-started',
article: 'authentication-options',
)
I18n.t('mfa.add')
end
end
19 changes: 19 additions & 0 deletions app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,15 @@ def multi_factor_auth_setup(multi_factor_auth_method:, **extra)
)
end

# Track when users get directed to the prompt requiring multiple MFAs for Phone MFA
def non_restricted_mfa_required_prompt_visited
track_event('Non-Restricted MFA Required Prompt visited')
end

def non_restricted_mfa_required_prompt_skipped
track_event('Non-Restricted MFA Required Prompt skipped')
end

# Tracks when an openid connect bearer token authentication request is made
# @param [Boolean] success
# @param [Hash] errors
Expand Down Expand Up @@ -1889,6 +1898,16 @@ def user_registration_2fa_setup(success:, errors: nil, **extra)
)
end

# Tracks when user visits Suggest Another MFA Page
def user_registration_suggest_another_mfa_notice_visited
track_event('User Registration: Suggest Another MFA Notice visited')
end

# Tracks when user skips Suggest Another MFA Page
def user_registration_suggest_another_mfa_notice_skipped
track_event('User Registration: Suggest Another MFA Notice Skipped')
end

# Tracks when user visits MFA selection page
def user_registration_2fa_setup_visit
track_event('User Registration: 2FA Setup visited')
Expand Down
19 changes: 7 additions & 12 deletions app/views/mfa_confirmation/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,19 @@

<p class='margin-top-1 margin-bottom-4'>
<%= @content.info %>
<% if @content.enforce_second_mfa? %>
<%= link_to(t('mfa.non_restricted.learn_more'), @content.learn_more) %>
<% end %>
</p>

<div class="col-12">
<%= link_to(
@next_path,
second_mfa_setup_path,
class: 'usa-button usa-button--wide usa-button--big margin-bottom-3',
) { @content.button } %>
</div>

<% unless @content.enforce_second_mfa? %>
<%= button_to(
auth_method_confirmation_skip_path,
method: :post,
class: 'usa-button usa-button--unstyled',
) do %>
<%= t('mfa.skip') %>
<% end %>
<%= button_to(
auth_method_confirmation_skip_path,
method: :post,
class: 'usa-button usa-button--unstyled',
) do %>
<%= t('mfa.skip') %>
<% end %>
27 changes: 27 additions & 0 deletions app/views/users/additional_mfa_required/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<% title @content.title %>

<%= image_tag asset_url('user-signup-ial1.svg'), width: 107, height: 119, alt: '', class: 'margin-bottom-4' %>

<%= render PageHeadingComponent.new.with_content(@content.title) %>

<p class='margin-top-1 margin-bottom-4'>
<%= @content.info %>
<%= link_to(@content.learn_more_text, @content.learn_more_link) %>
</p>

<div class="col-12">
<%= link_to(
second_mfa_setup_path,
class: 'usa-button usa-button--wide usa-button--big margin-bottom-3',
) { @content.button } %>
</div>

<% unless @content.cant_skip_anymore? %>
<%= button_to(
login_additional_mfa_required_skip_path,
method: :post,
class: 'usa-button usa-button--unstyled',
) do %>
<%= @content.skip %>
<% end %>
<% end %>
4 changes: 2 additions & 2 deletions app/views/users/mfa_selection/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<%= title t('two_factor_authentication.two_factor_choice') %>
<%= title t('mfa.additional_mfa_required.heading') %>

<%= render PageHeadingComponent.new.with_content(t('two_factor_authentication.two_factor_choice')) %>
<%= render PageHeadingComponent.new.with_content(t('mfa.additional_mfa_required.heading')) %>

<p class="maxw-mobile-lg margin-bottom-0"><%= @presenter.intro %></p>

Expand Down
5 changes: 4 additions & 1 deletion config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ irs_attempt_api_event_count_default: 1000
irs_attempt_api_event_count_max: 10000
kantara_2fa_phone_restricted: false
kantara_2fa_phone_existing_user_restriction: false
kantara_restriction_enforcement_date: '2022-07-19'
liveness_checking_enabled: false
logins_per_ip_track_only_mode: false
# LexisNexis #####################################################
Expand Down Expand Up @@ -298,7 +299,8 @@ development:
identity_pki_local_dev: true
idv_api_enabled_steps: '["password_confirm", "personal_key","personal_key_confirm"]'
kantara_2fa_phone_restricted: true
kantara_2fa_phone_existing_user_restriction: false
kantara_2fa_phone_existing_user_restriction: true
kantara_restriction_enforcement_date: '2022-07-01'
irs_attempt_api_public_key: MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyut9Uio5XxsIUVrXARqCoHvcMVYT0p6WyU1BnbhxLRW4Q60p+4Bn32vVOt9nzeih7qvauYM5M0PZdKEmwOHflqPP+ABfKhL+6jxBhykN5P5UY375wTFBJZ20Fx8jOJbRhJD02oUQ49YKlDu3MG5Y0ApyD4ER4WKgxuB2OdyQKd9vg2ZZa+P2pw1HkFPEin0h8KBUFBeLGDZni8PIJdHBP6dA+xbayGBxSM/8xQC0JIg6KlGTcLql37QJIhP2oSv0nAJNb6idFPAz0uMCQDQWKKWV5FUDCsFVH7VuQz8xUCwnPn/SdaratB+29bwUpVhgHXrHdJ0i8vjBEX7smD7pI8CcFHuVgACt86NMlBnNCVkwumQgZNAAxe2mJoYcotEWOnhCuMc6MwSj985bj8XEdFlbf4ny9QO9rETd5aYcwXBiV/T6vd637uvHb0KenghNmlb1Tv9LMj2b9ZwNc9C6oeCnbN2YAfxSDrb8Ik+yq4hRewOvIK7f0CcpZYDXK25aHXnHm306Uu53KIwMGf1mha5T5LWTNaYy5XFoMWHJ9E+AnU/MUJSrwCAITH/S0JFcna5Oatn70aTE9pISATsqB5Iz1c46MvdrxD8hPoDjT7x6/EO316DZrxQfJhjbWsCB+R0QxYLkXPHczhB2Z0HPna9xB6RbJHzph7ifDizhZoMCAwEAAQ==
liveness_checking_enabled: true
logins_per_ip_limit: 5
Expand Down Expand Up @@ -371,6 +373,7 @@ production:
irs_attempt_api_public_key: change-me-pls
kantara_2fa_phone_restricted: false
kantara_2fa_phone_existing_user_restriction: false
kantara_restriction_enforcement_date: '2022-07-19'
logins_per_ip_limit: 20
logins_per_ip_period: 20
logins_per_ip_track_only_mode: true
Expand Down
19 changes: 12 additions & 7 deletions config/locales/mfa/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ en:
account_info: Adding another authentication method prevents you from getting
locked out of your account if you lose one of your methods.
add: Add another method
info: Add another layer of security by selecting a multi-factor authentication
method. We recommend you select at least (2) two different options in case
you lose one of your methods.
non_restricted:
additional_mfa_required:
button: Add an authentication method
heading: Add another authentication method.
info: You opted to receive a code by SMS/text or a phone call to sign in after
you entered your email and password. You are now required to add another
authentication method as a backup in case you lose access to your phone.
info: Beginning %{date}, you will be required to add another authentication
method in case you lose access to your phone. Adding another
authentication method helps you avoid getting locked out of your
account. Learn more about authentication options
learn_more: Learn more about authentication options
non_restricted_required_info: You are required to add another authentication
method as a backup in case you lose access to your phone.
title: Add another authentication method before %{date}
info: Add another layer of security by selecting a multi-factor authentication
method. We recommend you select at least (2) two different options in case
you lose one of your methods.
second_method_warning:
link: Add a second authentication method.
text: You will have to delete your account and start over if you lose your only
authentication method.
skip: Skip for now
skip_once: Skip once
Loading