-
Notifications
You must be signed in to change notification settings - Fork 167
Refactor handling of successful two-factor phone confirmation #8347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ def create | |
| result = otp_verification_form.submit | ||
| post_analytics(result) | ||
| if result.success? | ||
| handle_valid_confirmation_otp if UserSessionContext.confirmation_context?(context) | ||
| handle_valid_otp(next_url: nil, auth_method: params[:otp_delivery_preference]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to pull
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. session context really only exists for phone OTPs, so I'm leaning towards making the I'm ultimately hoping this controller will be something like: if UserSessionContext.confirmation_context?(context)
handle_valid_confirmation_otp
handle_valid_verification_for_confirmation
else
handle_valid_verification_for_authentication
endand the remaining auth controllers can call |
||
| else | ||
| handle_invalid_otp(context: context, type: 'otp') | ||
|
|
@@ -29,6 +30,11 @@ def create | |
|
|
||
| private | ||
|
|
||
| def handle_valid_confirmation_otp | ||
| assign_phone | ||
| flash[:success] = t('notices.phone_confirmed') | ||
| end | ||
|
|
||
| def otp_verification_form | ||
| OtpVerificationForm.new(current_user, sanitized_otp_code) | ||
| end | ||
|
|
@@ -162,8 +168,75 @@ def phone_view_data | |
| }.merge(generic_data) | ||
| end | ||
|
|
||
| def display_phone_to_deliver_to | ||
| if UserSessionContext.authentication_or_reauthentication_context?(context) | ||
| phone_configuration.masked_phone | ||
| else | ||
| user_session[:unconfirmed_phone] | ||
| end | ||
| end | ||
|
|
||
| def unconfirmed_phone? | ||
| user_session[:unconfirmed_phone] && UserSessionContext.confirmation_context?(context) | ||
| end | ||
|
|
||
| def confirmation_for_add_phone? | ||
| UserSessionContext.confirmation_context?(context) && user_fully_authenticated? | ||
| end | ||
|
|
||
| def check_sp_required_mfa | ||
| check_sp_required_mfa_bypass(auth_method: params[:otp_delivery_preference]) | ||
| end | ||
|
|
||
| def assign_phone | ||
| @updating_existing_number = user_session[:phone_id].present? | ||
|
|
||
| if @updating_existing_number | ||
| phone_changed | ||
| else | ||
| phone_confirmed | ||
| end | ||
|
|
||
| update_phone_attributes | ||
| end | ||
|
|
||
| def update_phone_attributes | ||
| UpdateUser.new( | ||
| user: current_user, | ||
| attributes: { phone_id: user_session[:phone_id], | ||
| phone: user_session[:unconfirmed_phone], | ||
| phone_confirmed_at: Time.zone.now, | ||
| otp_make_default_number: selected_otp_make_default_number }, | ||
| ).call | ||
| end | ||
|
|
||
| def phone_changed | ||
| create_user_event(:phone_changed) | ||
| send_phone_added_email | ||
| end | ||
|
|
||
| def phone_confirmed | ||
| create_user_event(:phone_confirmed) | ||
| # If the user has MFA configured, then they are not adding a phone during sign up and are | ||
| # instead adding it outside the sign up flow | ||
| return unless MfaPolicy.new(current_user).two_factor_enabled? | ||
| send_phone_added_email | ||
| end | ||
|
|
||
| def send_phone_added_email | ||
| _event, disavowal_token = create_user_event_with_disavowal(:phone_added, current_user) | ||
| current_user.confirmed_email_addresses.each do |email_address| | ||
| UserMailer.with(user: current_user, email_address: email_address). | ||
| phone_added(disavowal_token: disavowal_token).deliver_now_or_later | ||
| end | ||
| end | ||
|
|
||
| def selected_otp_make_default_number | ||
| params&.dig(:otp_make_default_number) | ||
| end | ||
|
|
||
| def direct_otp_code | ||
| current_user.direct_otp if FeatureManagement.prefill_otp_codes? | ||
| end | ||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify my understanding, currently this only happens for phones, but eventually we'd want this method to be called for any MFA in the confirmation context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s my plan, yeah