Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def track_mfa_method_added
mfa_user = MfaContext.new(current_user)
mfa_count = mfa_user.enabled_mfa_methods_count
analytics.multi_factor_auth_added_phone(enabled_mfa_methods_count: mfa_count)
Funnel::Registration::AddMfa.call(current_user.id, 'phone')
Funnel::Registration::AddMfa.call(current_user.id, 'phone', analytics)
end

def handle_valid_otp_for_authentication_context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ def analytics_properties
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
phone_configuration_id: user_session[:phone_id] ||
current_user.default_phone_configuration&.id,
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow?,
enabled_mfa_methods_count: mfa_context.enabled_mfa_methods_count,
}
end
end
Expand Down
11 changes: 11 additions & 0 deletions app/controllers/users/additional_mfa_required_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ def skip
).call
end
analytics.non_restricted_mfa_required_prompt_skipped
# should_count as complete as well
analytics.user_registration_mfa_setup_complete(
mfa_method_counts: mfa_context.enabled_two_factor_configuration_counts_hash,
enabled_mfa_methods_count: mfa_context.enabled_mfa_methods_count,
pii_like_keypaths: [[:mfa_method_counts, :phone]],
success: true,
)
redirect_to after_sign_in_path_for(current_user)
end

Expand All @@ -28,6 +35,10 @@ def enforcement_date
@enforcement_date ||= IdentityConfig.store.kantara_restriction_enforcement_date
end

def mfa_context
@mfa_context ||= MfaContext.new(current_user)
end

def confirm_user_fully_authenticated
unless user_fully_authenticated?
return confirm_two_factor_authenticated(sp_session[:request_id])
Expand Down
12 changes: 11 additions & 1 deletion app/controllers/users/backup_code_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def edit; end

def continue
flash[:success] = t('notices.backup_codes_configured')
analytics.multi_factor_auth_setup(**analytics_properties)
redirect_to next_setup_path || after_mfa_setup_path
end

Expand All @@ -54,7 +55,7 @@ def track_backup_codes_created
analytics.backup_code_created(
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
)
Funnel::Registration::AddMfa.call(current_user.id, 'backup_codes')
Funnel::Registration::AddMfa.call(current_user.id, 'backup_codes', analytics)
end

def mfa_user
Expand Down Expand Up @@ -111,5 +112,14 @@ def authorize_backup_code_disable
return if MfaPolicy.new(current_user).multiple_non_restricted_factors_enabled?
redirect_to account_two_factor_authentication_path
end

def analytics_properties
{
success: true,
multi_factor_auth_method: 'backup_codes',
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow?,
enabled_mfa_methods_count: mfa_context.enabled_mfa_methods_count,
}
end
end
end
12 changes: 10 additions & 2 deletions app/controllers/users/piv_cac_authentication_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def piv_cac_service_url_with_redirect

def process_piv_cac_setup
result = user_piv_cac_form.submit
analytics.multi_factor_auth_setup(**result.to_h)
properties = result.to_h.merge(analytics_properties)
analytics.multi_factor_auth_setup(**properties)
if result.success?
process_valid_submission
else
Expand Down Expand Up @@ -121,7 +122,7 @@ def track_mfa_method_added
analytics.multi_factor_auth_added_piv_cac(
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
)
Funnel::Registration::AddMfa.call(current_user.id, 'piv_cac')
Funnel::Registration::AddMfa.call(current_user.id, 'piv_cac', analytics)
end

def piv_cac_enabled?
Expand Down Expand Up @@ -150,6 +151,13 @@ def good_nickname
name.present? && !PivCacConfiguration.exists?(user_id: current_user.id, name: name)
end

def analytics_properties
{
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow?,
enabled_mfa_methods_count: mfa_context.enabled_mfa_methods_count,
}
end

def cap_piv_cac_count
return unless IdentityConfig.store.max_piv_cac_per_account <= current_cac_count
redirect_to account_two_factor_authentication_path
Expand Down
10 changes: 9 additions & 1 deletion app/controllers/users/piv_cac_setup_from_sign_in_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def render_prompt

def process_piv_cac_setup
result = user_piv_cac_form.submit
analytics.multi_factor_auth_setup(**result.to_h)
properties = result.to_h.merge(analytics_properties)
analytics.multi_factor_auth_setup(**properties)
if result.success?
process_valid_submission
else
Expand Down Expand Up @@ -66,5 +67,12 @@ def process_valid_submission
create_user_event(:piv_cac_enabled)
redirect_to login_add_piv_cac_success_url
end

def analytics_properties
{
in_multi_mfa_selection_flow: false,
enabled_mfa_methods_count: MfaContext.new(current_user).enabled_mfa_methods_count,
}
end
end
end
12 changes: 10 additions & 2 deletions app/controllers/users/totp_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def new
def confirm
result = totp_setup_form.submit

analytics.multi_factor_auth_setup(**result.to_h)
properties = result.to_h.merge(analytics_properties)
analytics.multi_factor_auth_setup(**properties)

if result.success?
process_valid_code
Expand Down Expand Up @@ -97,7 +98,7 @@ def create_events
analytics.multi_factor_auth_added_totp(
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
)
Funnel::Registration::AddMfa.call(current_user.id, 'auth_app')
Funnel::Registration::AddMfa.call(current_user.id, 'auth_app', analytics)
end

def process_successful_disable
Expand Down Expand Up @@ -140,5 +141,12 @@ def cap_auth_app_count
def current_auth_app_count
current_user.auth_app_configurations.count
end

def analytics_properties
{
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow?,
pii_like_keypaths: [[:mfa_method_counts, :phone]],
}
end
end
end
11 changes: 9 additions & 2 deletions app/controllers/users/webauthn_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def confirm
remember_device_default: remember_device_default,
platform_authenticator: @platform_authenticator,
)
analytics.multi_factor_auth_setup(**result.to_h)
properties = result.to_h.merge(analytics_properties)
analytics.multi_factor_auth_setup(**properties)
if result.success?
process_valid_webauthn(form)
else
Expand Down Expand Up @@ -135,7 +136,7 @@ def process_valid_webauthn(form)
platform_authenticator: form.platform_authenticator?,
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
)
Funnel::Registration::AddMfa.call(current_user.id, 'webauthn')
Funnel::Registration::AddMfa.call(current_user.id, 'webauthn', analytics)
mark_user_as_fully_authenticated
handle_remember_device
if form.platform_authenticator?
Expand All @@ -147,6 +148,12 @@ def process_valid_webauthn(form)
redirect_to next_setup_path || after_mfa_setup_path
end

def analytics_properties
{
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow?,
}
end

def handle_remember_device
save_user_opted_remember_device_pref
save_remember_device_preference
Expand Down
9 changes: 9 additions & 0 deletions app/forms/totp_setup_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,23 @@ def process_valid_submission
user.save!
end

def mfa_context
user
end

def extra_analytics_attributes
{
totp_secret_present: secret.present?,
multi_factor_auth_method: 'totp',
auth_app_configuration_id: @auth_app_config&.id,
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
}
end

def mfa_user
MfaContext.new(user)
end

def create_auth_app(user, secret, new_timestamp, name)
@auth_app_config = Db::AuthAppConfiguration.create(user, secret, new_timestamp, name)
end
Expand Down
1 change: 1 addition & 0 deletions app/forms/two_factor_options_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def mfa_user
def extra_analytics_attributes
{
selection: selection,
selected_mfa_count: selection.count,
enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
}
end
Expand Down
26 changes: 25 additions & 1 deletion app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1325,10 +1325,16 @@ def multi_factor_auth_max_sends

# Tracks when a user sets up a multi factor auth method
# @param [String] multi_factor_auth_method
def multi_factor_auth_setup(multi_factor_auth_method:, **extra)
# @param [Boolean] in_multi_mfa_selection_flow
# @param [integer] enabled_mfa_methods_count
def multi_factor_auth_setup(multi_factor_auth_method:,
enabled_mfa_methods_count:, in_multi_mfa_selection_flow:,
**extra)
track_event(
'Multi-Factor Authentication Setup',
multi_factor_auth_method: multi_factor_auth_method,
in_multi_mfa_selection_flow: in_multi_mfa_selection_flow,
enabled_mfa_methods_count: enabled_mfa_methods_count,
**extra,
)
end
Expand Down Expand Up @@ -2094,11 +2100,13 @@ def user_registration_2fa_additional_setup_visit
# @param [Boolean] success
# @param [Hash] errors
# @param [Integer] enabled_mfa_methods_count
# @param [Integer] selected_mfa_count
# @param ['voice', 'auth_app'] selection
# Tracks when the the user has selected and submitted MFA auth methods on user registration
def user_registration_2fa_setup(
success:,
errors: nil,
selected_mfa_count: nil,
enabled_mfa_methods_count: nil,
selection: nil,
**extra
Expand All @@ -2108,13 +2116,29 @@ def user_registration_2fa_setup(
{
success: success,
errors: errors,
selected_mfa_count: selected_mfa_count,
enabled_mfa_methods_count: enabled_mfa_methods_count,
selection: selection,
**extra,
}.compact,
)
end

# @param [String] mfa_method
# Tracks when the the user fully registered by submitting their first MFA method into the system
def user_registration_user_fully_registered(
mfa_method:,
**extra
)
track_event(
'User Registration: User Fully Registered',
{
mfa_method: mfa_method,
**extra,
}.compact,
)
end

# @param [Boolean] success
# @param [Hash] mfa_method_counts
# @param [Integer] enabled_mfa_methods_count
Expand Down
25 changes: 13 additions & 12 deletions app/services/funnel/registration/add_mfa.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
module Funnel
module Registration
class AddMfa
def self.call(user_id, mfa_method)
def self.call(user_id, mfa_method, analytics)
now = Time.zone.now
funnel = RegistrationLog.find_by(user_id: user_id)
return if funnel.blank? || funnel.second_mfa.present?

params = if funnel.first_mfa.present?
{
second_mfa: mfa_method,
}
else
{
first_mfa: mfa_method,
first_mfa_at: now,
registered_at: now,
}
end
if funnel.first_mfa.present?
params = {
second_mfa: mfa_method,
}
else
params = {
first_mfa: mfa_method,
first_mfa_at: now,
registered_at: now,
}
analytics.user_registration_user_fully_registered(mfa_method: mfa_method)
end

funnel.update!(params)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}

expect(@analytics).to receive(:track_event).
Expand Down Expand Up @@ -102,6 +104,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}
stub_analytics
expect(@analytics).to receive(:track_mfa_submit_event).
Expand Down Expand Up @@ -151,6 +155,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}

stub_analytics
Expand Down Expand Up @@ -206,6 +212,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}

stub_analytics
Expand Down Expand Up @@ -334,6 +342,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}

expect(@analytics).to receive(:track_event).
Expand Down Expand Up @@ -400,6 +410,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 1,
in_multi_mfa_selection_flow: false,
}

expect(@analytics).to have_received(:track_event).
Expand Down Expand Up @@ -448,6 +460,8 @@
area_code: parsed_phone.area_code,
country_code: parsed_phone.country,
phone_fingerprint: Pii::Fingerprinter.fingerprint(parsed_phone.e164),
enabled_mfa_methods_count: 0,
in_multi_mfa_selection_flow: false,
}

expect(@analytics).to have_received(:track_event).
Expand Down
Loading