Skip to content
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

Implement 2FA recovery codes #5800

Closed
ronaldoussoren opened this issue May 7, 2019 · 18 comments · Fixed by #7260
Closed

Implement 2FA recovery codes #5800

ronaldoussoren opened this issue May 7, 2019 · 18 comments · Fixed by #7260
Labels
feature request help needed We'd love volunteers to advise on or help fix/implement this.

Comments

@ronaldoussoren
Copy link

What's the problem this feature will solve?
The new 2FA feature adds a TOTP second factor to the authentication proces. This can be problematic when you lose access to the device you use for the 2FA authentication (e.g. the phone running the TOTP app).

Describe the solution you'd like
Most TOTP using sites I've used have an option of recovery codes that can be used to log in with a recovery code when you've lost access to the TOTP device.

Additional context

Github documentation on account recovery for 2FA

@di
Copy link
Member

di commented May 8, 2019

#5758 ("Define manual account recovery process") is related.

@brainwane
Copy link
Contributor

Per conversation in IRC today -- recovery codes, while a useful feature, are not in-scope for the deliverables we promised in our grant-funded work from the Open Technology Fund (more details). So right now we'll continue with the current workflow, where it falls on PyPI site admins to perform the recovery process on behalf of users, and if we have time in this grant, we'll prioritize doing this, but otherwise we will work on it on a volunteer basis afterward.

@woodruffw
Copy link
Member

To follow up on @nurupo's question in #996:

All 2FA implementations I have seen have a backup method you can use if you lose your TOTP/U2F device. Often times they provide backup codes. Sometimes it's TOTP with SMS as backup, or U2F with TOTP as backup. But I think I have yet to see a 2FA without a backup method.

If a user has both TOTP and WebAuthn enabled but has lost access to one or the other, they'll still be able to use the one they still have access to. That's not a backup scheme per se since we impose no ordering between TOTP and WebAuthn, but it's something we'll support.

Re: SMS and recovery codes: like @brainwane said these are not in scope for the OTF work, but it's my professional opinion that SMS should not be either a second-factor or recovery option in any greenfield 2FA implementation. Recovery codes are a great idea and IIRC are on the PyPI roadmap, but (again IMO) should not be mandatory, as they circumvent the two factor scheme entirely. Users who don't enable recovery codes will then be at the mercy of the recovery process determined by the site admins.

@nurupo
Copy link

nurupo commented May 22, 2019

An issue with using both TOTP and WebAuthn is that if you use a single device for both, e.g. a Yubikey can do both TOTP and WebAuthn, and lose it, then you won't have access to both of those. Of course the obvious solution would be "don't store them on the same device". Or you could treat TOTP secret as a backup code and write it somewhere down as you would with backup codes. So I guess either way it somehow works out in the end, so I'm fine with just TOTP and WebAuthn. Having recovery codes would be a huge improvement though.

it's my professional opinion that SMS should not be either a second-factor or recovery option in any greenfield 2FA implementation.

Of course, please do not use SMS, it's considered insecure as it's subject to being intercepted and you can social engineer phone companies to assign you target's phone number, not to mention it would cost money to send messages to users. I mentioned SMS purely as an example of what I have seen in the wild, not necessarily as a model that should be followed.

as they circumvent the two factor scheme entirely.

Not sure how a website giving a user recovery codes "circumvents the two factor scheme entirely" any more than a website giving a user a TOTP secret. Both are shared secrets known to the website. Both can be written down. Both can be used for 2FA.

Users who don't enable recovery codes will then be at the mercy of the recovery process determined by the site admins.

I'm not following, what does this have to do with recovery codes? You could apply this to any 2FA method. For example, users who enable just WebAuthn but lose their key "will then be at the mercy of the recovery process determined by the site admins."

@nurupo
Copy link

nurupo commented May 22, 2019

Anyway, thanks for letting know, I'm glad that recovery codes are on the PyPI road-map, even if not as part of the OTF work.

@woodruffw
Copy link
Member

woodruffw commented May 22, 2019

Not sure how a website giving a user recovery codes "circumvents the two factor scheme entirely" any more than a website giving a user a TOTP secret. Both are shared secrets known to the website. Both can be written down. Both can be used for 2FA.

Yeah, this is admittedly a hazy distinction. TOTP preserves the second factor property by requiring a transform on the secret + windowed timestamp that the user (probably) can't do in their head and thus turn into something they know, but a user could always save their TOTP secret somewhere that isn't sequestered and violate the scheme in that way.

OTOH, recovery codes are (usually) trivial for users to memorize. They probably won't memorize them so maybe that's a moot distinction, but it's common enough to see people save their codes on disk instead of printing them out, stash them in their password managers, &c. Combined with the absence of a transform that humans can't easily perform, I'd say this compromises their ability to be a "real" second factor. Admittedly nitpicky.

I'm not following, what does this have to do with recovery codes? You could apply this to any 2FA method. For example, users who enable just WebAuthn but lose their key "will then be at the mercy of the recovery process determined by the site admins."

Ah, sorry. Implicit in that is the assumption that account recovery requests won't be honored if the account in question has 2FA enabled and the user can't prove that they possess the second factor. But I don't know if that's actually been settled on yet.

@brainwane brainwane added the help needed We'd love volunteers to advise on or help fix/implement this. label Jun 21, 2019
@nlhkabu
Copy link
Contributor

nlhkabu commented Jun 22, 2019

Note: we already have draft help text for this feature. I've copied this from #5586


What is a recovery code?

When setting up two factor authentication on your account, you were provided with the option to add a set of 8 recovery codes, and instructed to keep these in a safe place.

These codes are usually a string of numbers, letters or words that act as a one time password. If you are unable to login to PyPI using your normal second factor, you can use one of these codes to bypass the 2FA process. Once you have used a recovery code, you cannot use it again.

It is important that you store these codes securely by either printing or writing down the codes - we strongly recommend that you do not store them in a password manager, or on any device.

If you lose your recovery codes, and cannot authenticate with one of your 2FA methods, you will be locked out of your PyPI account. The PyPI team can manually grant you access to your account under limited circumstances.

TODO:

  • Update These codes are usually a string of numbers, letters or words to reflect the actual structure of the recovery codes we implement
  • Once we have manual recovery guidelines (see Define manual account recovery process #5758), link to them from The PyPI team can manually grant you access to your account under limited circumstances.

@nlhkabu
Copy link
Contributor

nlhkabu commented Jun 23, 2019

Mockups for this feature can be found here: #5587

TLDR:

  • Add link to recovery code page under each 2FA method
  • Ensure instructional UI text explains that using a recovery code is bypassing 2FA (maybe we also need to mention here that once used, a recovery code cannot be used again).

@cool-RR

This comment has been minimized.

@pidugusundeep

This comment has been minimized.

@cool-RR

This comment has been minimized.

@pidugusundeep

This comment has been minimized.

@ewdurbin

This comment has been minimized.

@yeraydiazdiaz
Copy link
Contributor

I've noticed the 2FA reset requests starting to pile up, showcasing first that users are happy with our current TOTP which is amazing, but also that our manual recovery approach is not sustainable as it increases the burden on admins and creates quite a bit of frustration for users.

I think we need to start defining the work necessary for this issue to be completed.

The conversation in #5586 is a good starting point, maybe we could refine the specifics of:

  1. The form of the recovery codes.
  2. When and how the user is prompted to create them.
  3. The recovery flow from the perspective of a locked out user.

cc @ewdurbin @di @brainwane @woodruffw @nlhkabu

@woodruffw
Copy link
Member

To copy some of the details from a conversation with @ewdurbin + some old notes:

Recovery code format

It should be hard and/or impossible for users to confuse their recovery codes with their TOTP tokens (this is less of a problem with a technical base like PyPI, but still happens). This can be accomplished by making the latter longer than the former, and/or using a different alphabet (alphanum instead of just numeric), and/or having an explicit separator (e.g. XXXX-XXXX).

Prompting users

IMO, it makes sense to make recovery code provisioning an explicit part of all 2FA (i.e., both TOTP and WebAuthn) flows: after provisioning their first 2FA method, users are unconditionally redirected to a page where recovery codes have been generated.

Standard practices apply: the codes should be selectable, should have print and save actions, and should come with a strong warning not to treat them as a 2FA bypass and protect them appropriately. Industry practice currently (mostly) splits between suggesting that the codes be printed out and stored somewhere or saved in a password manager; recommending either or both is fine IMO.

Depending on how mandatory you'd like recovery codes to be, you can ask users to use one to complete the 2FA + recovery provisioning process.

Recovery flow

The flow when using a recovery code should be identical to the 2FA flow, since recovery codes behave as just a 2FA bypass: users should still be required to enter their password. It'd be appropriate to record additional UserEvents for the consumption of recovery tokens.

@brainwane
Copy link
Contributor

(I imagine the support headache will increase further now that we've publicized 2FA more widely (announcement email, blog post).)

@ewdurbin
Copy link
Member

Implementation in progress in #7260

@brainwane
Copy link
Contributor

Thank you @ewdurbin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request help needed We'd love volunteers to advise on or help fix/implement this.
Projects
None yet
Development

Successfully merging a pull request may close this issue.