Improve 2FA Recovery Flow
## Problem Statement
Users are often locked out of their accounts when they lose their 2FA device. If a user loses their recovery codes or don't have a backup recovery method, their only remaining option is to contact Support (for GitLab.com) or their instance admin (for self-managed).
This is problematic for users who experience a lot of friction in the recovery process and for GitLab.com because it introduces a risk vector: people. The additional friction can drastically degrade the user experience for our wider community and the involvement of people from GitLab can open up social engineering or other risk vectors that could affect account security.
## Reach
10.0 = Impacts the vast majority (~80% or greater) of our users, prospects, or customers.
## Impact and Confidence
3.0 = Massive impact
100% = High confidence
This would have a significant impact in two ways:
- Users would be able to get access to their account without contacting Support
- Support would no longer need to [answer a large number of tickets](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/1715#note_279585210) from users locked out of their account, which would also [reduce cost](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/1715#note_304856359); this would also apply to GitLab self-managed admins who can save time
## Current workflow and available options
When a user wants to set up 2FA, they can go their account page and [enable 2FA](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html#enabling-2fa). Currently, there are two options:
1. 2FA app
1. U2F (e.g. Yubikey)
Once set up, they receive their one time use *download codes* which they should save to use later.
If a user loses the device, the possible ways to get access to the account:
1. Use the other 2FA option (e.g. Yubikey if they lost their phone with 2FA app) if it's been set up.
1. Use a download code not previously used.
1. Generate new codes [using SSH](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html#generate-new-recovery-codes-using-ssh).
## Objectives
We would like to remove the human factor in the process.
> The explicit point of something like 2FA and U2F is to lock out access to those who do not have them. Their purpose is diminished if we have policies that allow them to be circumvented.
from https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/1715 (see also, for a lot more discussion and rationale)
### Adding recovery methods
Based on discussions, the best options are:
1. Email code to verified email (must be a separate email from password reset, which is currently primary email only) https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_342311912 -- This option would allow free users to have a recovery path.
1. Trusted contact as per https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_311486271 -- This option mirrors the process that is currently followed for users in large groups.
Options discussed but not prioritized at this time (in preferred order high to low):
1. Using existing session (number of cases this would apply to?)
1. Unique information for the user to verify. e.g. latest commit info in given private repo path
1. Trusted linked account (e.g. GitHub uses Facebook)
1. Security questions
1. PAT: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63281
1. enforce SSH key with 2FA: https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/2207 (low ease of use)
1. SMS code: https://gitlab.com/gitlab-org/gitlab/-/issues/30026 (too many security concerns, but better than nothing); Note: [this research from Google](https://security.googleblog.com/2019/05/new-research-how-effective-is-basic.html), which suggests that in spite of the security risks of using SMS codes, an SMS code sent to a recovery phone number helped block 76% of targeted attacks, so one may consider offering it as a fallback
### Next Steps
1. https://gitlab.com/gitlab-org/gitlab/-/issues/219050 -- Complete this work and measure change in resets requested.
1. ~If there is no change then next step would be https://gitlab.com/gitlab-org/gitlab/-/issues/225766 and https://gitlab.com/gitlab-org/gitlab/-/issues/219051.~
1. ~Last step is to work on https://gitlab.com/gitlab-org/gitlab/-/issues/225767 to further automate the process for paid users.~
Based on analysis/report in https://gitlab.com/groups/gitlab-org/-/epics/3783#note_901850015 the next steps should be:
1. gitlab#372401 to allow paid organizations to self-serve -- highest priority and largest cost savings
2. gitlab#219051 to prevent users from losing 2FA
3. Additional method for recovery for both paid and free users: gitlab#225766
### More background
For other suggestions and possible follow up issues, please refer to these comments in particular
1. https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_330927903
1. https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_331026753
1. https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_333991331
1. https://gitlab.com/gitlab-org/gitlab/-/issues/211755#note_344506422
epic