Use recovery codes and access keys instead of one time passwords #1531

Open
opened 2025-11-02 04:04:01 -06:00 by GiteaMirror · 5 comments
Owner

Originally created by @rugk on GitHub (Feb 13, 2018).

Description

I think you've got the one-time passwords for 2FA wrong…

The concrete problem is https://github.com/go-gitea/gitea/issues/3507, but I think the general thing is a bit wrong.
E.g. the text when generating an one-time password states "when you've logged in with your one-time password, you can generate a new one here". That's not what such a password is for…
So let's skip the problems part and directly explain how it should be done…

This is how such things are handled (in GitHub e.g.). You have two types of static "passwords":

  • recovery codes
    • That is what you probably mean with the current "one time passwords", but they are numbers only!
    • Usually multiple ones are generated (so you can print them and place some of them in different places)
    • When one lost their 2FA device, one can use such a code instead of the 2FA code.
    • You can only skip the 2FA step, not the password login!
    • After use, they are invalidated and cannot be used again. A mail is sent to the user's mail in order to notice them that such a password was used.
    • Usually one can display them later in the UI.
    • example: 447837 and 143782 and 01783
    • alternatively, you can provide a "lost device" link on the 2FA validation page and have separate, static passwords with letters, which are more secure, i.e. wOXJlI. (that's how GitHub does it)
  • access tokens (per device!)
    • quite long (longer than what you currently issue!), treat them as "API keys"
    • They can be saved on a device for git (.git-credentials even allows that) and are automatically used for authentication.
    • You can always use them like a password, but one should not be able to use them from the web interface. (as they should be "bound" to a device)
    • The reason why they exist is to allow login on devices, where 2FA input is not supported. (i.e. git) Otherwise we would not need them and just input 2FA codes.
    • Only shown once to prevent the user from reusing it for multiple devices.
    • They are the only way to authenticate without entering a 2FA code. (i.e. what https://github.com/go-gitea/gitea/issues/1394 was about)
    • Important: They get some label/name, which can be shown in the user's profile. There they can be removed/revoked, e.g. when you've lost a device. That is the whole thing, which makes them useful.
    • example: Gpma2pzZGtsZmprc2RqZmxramRzw7xvd3FlMHFlcmlxd3Bva

Conclusion

So as you see these are two things, with very different purposes. You cannot mix them (as you did currently) and really have to offer two things for that.
Generally, you can have a look at GitHub, where they've implemented it in a pretty decent way.

Originally created by @rugk on GitHub (Feb 13, 2018). ## Description I think you've got the one-time passwords for 2FA wrong… The concrete problem is https://github.com/go-gitea/gitea/issues/3507, but I think the general thing is a bit wrong. E.g. the text when generating an one-time password states "when you've logged in with your one-time password, you can generate a new one here". That's not what such a password is for… So let's skip the problems part and directly explain how it should be done… This is how such things are handled (in GitHub e.g.). You have two types of static "passwords": * recovery codes * That is what you probably mean with the current "one time passwords", but they are numbers only! * Usually **multiple** ones are generated (so you can print them and place some of them in different places) * When one lost their 2FA device, one can use such a code **instead of the 2FA code**. * You can **only** skip the 2FA step, not the password login! * After use, they are **invalidated** and cannot be used again. A mail is sent to the user's mail in order to notice them that such a password was used. * Usually one can display them later in the UI. * example: `447837` and `143782` and `01783` * alternatively, you can provide a "lost device" link on the 2FA validation page and have separate, static passwords with letters, which are more secure, i.e. `wOXJlI`. (that's how GitHub does it) * access tokens (per device!) * quite long (longer than what you currently issue!), treat them as "API keys" * They can be saved on a device for git ([`.git-credentials` even allows that](https://git-scm.com/docs/git-credential-store)) and are automatically used for authentication. * You can always use them like a password, but one should not be able to use them from the web interface. (as they should be "bound" to a device) * The reason why they exist is to allow login on devices, where 2FA input is not supported. (i.e. git) Otherwise we would not need them and just input 2FA codes. * Only shown once to prevent the user from reusing it for multiple devices. * They are the only way to authenticate without entering a 2FA code. (i.e. what https://github.com/go-gitea/gitea/issues/1394 was about) * **Important:** They get some label/name, which can be shown in the user's profile. There they **can be removed/revoked**, e.g. when you've lost a device. That is the whole thing, which makes them useful. * example: `Gpma2pzZGtsZmprc2RqZmxramRzw7xvd3FlMHFlcmlxd3Bva` ## Conclusion So as you see these are two things, with very **different** purposes. You cannot mix them (as you did currently) and really have to offer two things for that. Generally, you can have a look at GitHub, where they've implemented it in a pretty decent way.
GiteaMirror added the type/proposal label 2025-11-02 04:04:01 -06:00
Author
Owner

@DasLeo commented on GitHub (Jul 2, 2018):

Totally agree with @rugk
Enabling 2FA prevents me from using any third party Git client, only asking for username and password.
Device keys like implemented in other applications e.g. Nextcloud helps in that situation.

At any time there would be the possiblity to removed any of those device passwords.

Or is there any possibilty to use Access Tokens in those situations for username or password?

@DasLeo commented on GitHub (Jul 2, 2018): Totally agree with @rugk Enabling 2FA prevents me from using any third party Git client, only asking for username and password. Device keys like implemented in other applications e.g. Nextcloud helps in that situation. At any time there would be the possiblity to removed any of those device passwords. Or is there any possibilty to use Access Tokens in those situations for username or password?
Author
Owner

@0x5c commented on GitHub (Jan 10, 2019):

Update on the state of this issue

Recovery codes ("I lost my 2FA device.")

  • The backup-codes are now behaving in the correct way.
  • Gitea still does not generate multiple backup codes.
  • The code(s) is not also available as a printable/saveable file (like everyone else does, even Discord).
  • The backup code(s) can now be used instead of a generated 2FA code (not directly, but with the "Use scratch code" link), and expires after one use.
  • Scratch codes are still not in the normal 2FA format: nnn nnn.
  • Still impossible to see the backup codes at a later date.

To check:

  • Is the user mailed when a scratch code is used?

"Application passwords" ("Oof, this app can't handle 2FA")

  • Now as long as they should (very long)
  • Now alphanumeric
  • Now behave like they should, and block use from the web interface (where 2FA works)
  • Now shown only once and never again
  • Now also the only way to login without 2FA codes or scratch codes
  • Now need to be assigned names by the user
  • Now can individually be revoked

Conclusion

Application passwords/tokens are now completely and correctly implemented (bar bugs, I'm not aware if there are some).
However, the state of 2FA is much different, with a lot to change.
Also, it should be decided if the scratch code should behave like they currently do, or as they do in most other services (GitHub, Google, etc): direct alternative to 2FA codes, which can be input in the normal 2FA box.

@0x5c commented on GitHub (Jan 10, 2019): # Update on the state of this issue ## Recovery codes *("I lost my 2FA device.")* - [x] The backup-codes are now behaving in the correct way. - [ ] Gitea still does not generate multiple backup codes. - [ ] The code(s) is not also available as a printable/saveable file (like everyone else does, even Discord). - [x] The backup code(s) can now be used instead of a generated 2FA code (not directly, but with the "Use scratch code" link), and expires after one use. - [ ] Scratch codes are still not in the normal 2FA format: `nnn nnn`. - [ ] Still impossible to see the backup codes at a later date. ### To check: - Is the user mailed when a scratch code is used? ## "Application passwords" *("Oof, this app can't handle 2FA")* - [x] Now as long as they should (very long) - [x] Now alphanumeric - [x] Now behave like they should, and block use from the web interface (where 2FA works) - [x] Now shown only once and never again - [x] Now also the only way to login without 2FA codes or scratch codes - [x] Now need to be assigned names by the user - [x] Now can individually be revoked ## Conclusion Application passwords/tokens are now completely and correctly implemented (bar bugs, I'm not aware if there are some). However, the state of 2FA is much different, with a lot to change. Also, it should be decided if the scratch code should behave like they currently do, or as they do in most other services (GitHub, Google, etc): direct alternative to 2FA codes, which can be input in the normal 2FA box.
Author
Owner

@rugk commented on GitHub (Jan 10, 2019):

Still impossible to see the backup codes at a later date.

That's good. IN such a case, a regeneration is better anyway.

@rugk commented on GitHub (Jan 10, 2019): > Still impossible to see the backup codes at a later date. That's good. IN such a case, a regeneration is better anyway.
Author
Owner

@0x5c commented on GitHub (Jan 10, 2019):

"regeneration code" what is that?

@0x5c commented on GitHub (Jan 10, 2019): "regeneration code" what is that?
Author
Owner

@0x5c commented on GitHub (Jan 10, 2019):

Most services (github, google, digitalocean, discord, etc) allow the user to see previously generated codes, after a confirmation of the password. This is standard practice.

@0x5c commented on GitHub (Jan 10, 2019): Most services (github, google, digitalocean, discord, etc) allow the user to see previously generated codes, after a confirmation of the password. This is standard practice.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#1531