Skip to content

Auto-enroll new users in email-based OTP behind feature flag

What does this MR do and why?

Auto-enroll new users in email-based OTP behind feature flag.

Blocked by Add email-based MFA with phased rollout support (!200749 - merged). After that is merged, we can point this MR at master.

This MR implements https://gitlab.com/gitlab-org/gitlab/-/issues/561385+s.

  • Add enrol_new_users_in_email_otp feature flag to control automatic enrollment of new users in email-based OTP during account creation. It uses an instance scope, as it is checked before the user record has been created.
  • Set email_otp_required_after to current time in Users::BuildService when feature flag is enabled.
  • Skip email-based OTP verification for users on their first sign-in (when last_sign_in_at is nil) to avoid double email verification during the signup flow with Devise::Confirmable
  • Add test coverage for enrollment behavior and first sign-in bypass logic

This maintains the existing signup UX while enabling automatic enrollment for mandatory MFA rollout. Users will only encounter email-based OTP on subsequent sign-ins after account confirmation.

Risks

  • This is a critical area of the code - when users are created. This code is used both by normal registration flows, by Admin actions, by features like Import presumably.
  • We are using an :instance type feature flag which doesn't allow careful rollout. It's simply on or off.
    • Mitigation The sign in flow Email-based OTP behavior is controlled by a user-based FF email_based_mfa. Even if we were to enable enrol_new_users_in_email_otp, it would be ineffective while email_based_mfa is disabled (by default, or for that user).

References

Screenshots or screen recordings

This screen recording shows:

  1. The existing, unchanged, registration flow:
    • Create your user
    • Check your email
    • Click the link
    • Redirected to the sign in page
    • Log in
    • See the dashboard
  2. Then, on next sign in, the new behaviour
    • Sign in as that same user
    • Prompted to enter a code
    • Check your email
    • Enter the code
    • Complete log in
    • See the dashboard

sign-up-flow-demo

How to set up and validate locally

Recall we have two FF involved in Email-based MFA.

Just this MR

To validate the behaviour of this feature being rolled out and just this FF being enabled:

  1. In a rails console, enable this MR's FF:
Feature.enable(:enrol_new_users_in_email_otp) # Introduced in this MR
  1. Register as a new user
  2. Visit /rails/letter_opener to confirm your email address. Note you are redirected to the sign in page.
  3. Sign in. Note that you sign in with just your username and password. This is the existing registration flow.
  4. Sign out.
  5. Sign in.
    • Note that you are not prompted to enter an Email-based OTP code
    • This is because Feature.enabled?(:email_based_mfa, user) is false

This confirms that the feature can ship with no user-perceivable difference, while still allowing for incremental percentage-based rollout using the Feature.enable(:email_based_mfa, user) flag. 👍

End state

When we roll this out, the "end state" is that two FFs would be enabled:

  1. In a rails console, emulate a state where the feature is completely rolled out:
Feature.enable(:enrol_new_users_in_email_otp) # Introduced in this MR
Feature.enable(:email_based_mfa) # Introduced in !200749
  1. Register as a new user
  2. Visit /rails/letter_opener to confirm your email address. Note you are redirected to the sign in page.
  3. Sign in.
    • Note that you sign in with just your username and password, even though email_based_mfa is enabled.
    • This is showing the existing registration flow remains unchanged
  4. Sign out.
  5. Sign in.

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.

Edited by Nick Malcolm

Merge request reports

Loading