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 enableenrol_new_users_in_email_otp
, it would be ineffective whileemail_based_mfa
is disabled (by default, or for that user).
-
Mitigation The sign in flow Email-based OTP behavior is controlled by a user-based FF
References
- The parent epic: https://gitlab.com/groups/gitlab-org/-/epics/18304
- The project epic: https://gitlab.com/groups/gitlab-org/-/epics/17128
- The Architecture Design doc: https://internal.gitlab.com/handbook/security/product_security/mandatory_mfa/architecture_design/
Screenshots or screen recordings
This screen recording shows:
- 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
- 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
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:
- In a rails console, enable this MR's FF:
Feature.enable(:enrol_new_users_in_email_otp) # Introduced in this MR
- Register as a new user
- Visit
/rails/letter_opener
to confirm your email address. Note you are redirected to the sign in page. - Sign in. Note that you sign in with just your username and password. This is the existing registration flow.
- Sign out.
- 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:
- 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
- Register as a new user
- Visit
/rails/letter_opener
to confirm your email address. Note you are redirected to the sign in page. - 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
- Note that you sign in with just your username and password, even though
- Sign out.
- Sign in.
- Note that you are now required to check your email and enter a code. This is functionality introduced in https://gitlab.com/gitlab-org/gitlab/-/issues/561385
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.