[go: up one dir, main page]

Draft: Add enrollment management for Email-based OTP

What does this MR do and why?

Automatically manages email_otp_required_after based on 2FA policies to prevent invalid authentication states. It also exposes the rationale for why email_otp_required_after can or cannot be modified by the user, so that we can expose that in the User Preferences in a subsequent MR.

See https://gitlab.com/gitlab-org/gitlab/-/issues/570173+s

Changes / Behaviour

  • New application setting: require_minimum_email_based_otp_for_users_with_passwords (not exposed in UI yet)
    • GitLab wants to roll Email OTP out as optional at first. This allows us to do that.
  • When users enable 2FA under mandatory policy: Email OTP is automatically disabled (no longer permitted as fallback). However, until they add 2FA, they still need to do Email-based OTP (if enrolled). This ensures we don't degrade security when that mandatory 2FA policy gets applied.
  • When users disable 2FA with minimum email OTP required: Email OTP is automatically re-enabled

Implementation

Uses before_validation + validate pattern to enforce data integrity. The setter ensures validation always succeeds, preventing existing records from becoming invalid. By adding the methods to the user as callbacks we ensure this authentication-critical data is never incorrect (compare with Avoid ActiveRecord Callbacks).

References

Screenshots or screen recordings

Before After

How to set up and validate locally

To get Email-based OTP configured (not this MR - already in master)

From https://internal.gitlab.com/handbook/security/product_security/mandatory_mfa/architecture_design/#useful-background

  1. Log in as admin and change the following settings (to match GitLab.com):
    • Under Admin > Settings > General > Sign-up restrictions:
      1. Turn off "Require admin approval for new sign-ups".
      2. Set "Email confirmation settings" to "Hard".
      3. Click "Save changes".
    • Under Admin > Settings > General > Sign-in restrictions:
      1. Turn on "Require email verification when account is locked.".
      2. Click "Save changes".

To test this MR's logic

  1. Enable flag for a user: Feature.enable(:email_based_otp, user)
  2. Enrol them in Email-based OTP: user.update!(email_otp_required_after: Time.current)
  3. Add user to group with 2FA enforcement
  4. Enable 2FA → observe email_otp_required_after becomes nil. When you sign in, you have to do 2FA, not email OTP.
  5. Remove the user from the group
  6. Disable 2FA → observe Email OTP is not required (because the instance doesn't require it)
  7. Update the application setting to enforce Email-based OTP: ``
  8. Note that you can still log out and in - the validation isn't causing your user to be invalid
  9. In practice, when we roll this out on GitLab.com, we will then also go and update email_otp_required_after to be some time in the future as per the https://gitlab.com/gitlab-org/gitlab/-/work_items/566491+s
  10. Update the user's email_otp_required_after.
  11. You can future or past date it, depending on what experience you want to test. We have a banner from 60-30 days in the future, a skippable prompt 30-0 days, then enforced if the date is now/the past.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

  • Test the MR's logic as per the above steps
  • Get Authentication review specifically

Merge request reports

Loading