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

Add support for two-factor authentication #1681

Closed
nijel opened this issue Nov 7, 2017 · 28 comments · Fixed by #12173
Closed

Add support for two-factor authentication #1681

nijel opened this issue Nov 7, 2017 · 28 comments · Fixed by #12173
Assignees
Labels
backlog This is not on the Weblate roadmap for now. Can be prioritized by sponsorship. enhancement Adding or requesting a new feature.
Milestone

Comments

@nijel
Copy link
Member

nijel commented Nov 7, 2017

Adding opt-in support for two-factor authentication might improve security for users. There are certainly several existing implementations for Django, the question is how they would plug into our customized python-social-auth based authentication pipeline.

Anyway it should support at least TOTP (Google Authenticator) and FIDO U2F (hardware keys).

@nijel nijel added the enhancement Adding or requesting a new feature. label Nov 7, 2017
@TheAssassin
Copy link

Great idea. I'd like to see this in Weblate.

@nijel
Copy link
Member Author

nijel commented Aug 21, 2019

These days it might be more reasonable to focus on webauhtn. There is PyWARP implementation requiring Python 3, what would be blocked by #2201

@TheAssassin
Copy link

Maybe as an addition, but in my experience, U2F etc. devices are pretty widely spread, same goes for TOTP etc. I guess having webauthn is nice to have, but U2F with a password is already quite strong, webauthn just adds some convenience while retaining a high security level.

@nijel
Copy link
Member Author

nijel commented Aug 21, 2019

U2F devices should be supported through webauthn, it is more generic browser API for authentication (at least this is my impression from that).

@TheAssassin
Copy link

I've seen that there is said to be some U2F downward compatibility from webauthn. I just ask you to ensure this compatibility, it seems that you need to set a few things up the right way to make it work.

That said, offering TOTP/HOTP in addition helps strengthen non-expert users' security, who might not be willing to invest in a U2F/webauthn device. Sure, it's not bulletproof, but can at least prevent a few attacks.

@nijel nijel added the backlog This is not on the Weblate roadmap for now. Can be prioritized by sponsorship. label Dec 5, 2019
@github-actions
Copy link

github-actions bot commented Dec 5, 2019

This issue has been added to backlog. It is not scheduled on our road map, but it might be eventually implemented. In case you desperately need this feature, please consider helping or funding the development.

@nijel
Copy link
Member Author

nijel commented May 10, 2021

Two years later I got back to this.

TOTP could be easily integrated using https://github.com/django-otp/django-otp, but this library is likely not to receive any improvements in the future.

WebAuthn has is a low-level module https://pypi.org/project/webauthn/, but I could not find any reasonable Django integration. There is a bunch of modules, but none of them seems maintained and in a good shape (see django-otp/django-otp#40 for some discussion).

Out of other libraries, the most promising looks https://github.com/mkalioby/django-mfa2 as it supports all we want, but it's maintenance status is not good.

In the end the most reliable approach might be to build this on low-level libraries as that would easily integrate into our python-social-auth based workflow.

Just for the reference, here is how this got integrated into pypi.org (they are using Flask, so it's slightly different): pypi/warehouse@59ab1f2 pypi/warehouse@6cbaf84

@TheAssassin
Copy link

Generally, it seems like U2F/Webauthn is either not implemented at all in many popular Python web applications, or in a proprietary, i.e., non-portable way. It's a bit of a shame that there are no good libraries available to just integrate yet. Of course, maintaining a library can be a lot of effort. But in a framework like Django there should have been an official solution available for years. </rant>

django-mfa2 actually looks quite good, there has been a release not too long ago even. I think once implemented, there is not a lot to improve on these modern auth mechanisms. The only issue might be the slightly complex integration into existing projects, but I'm quite confident you would manage to get it done. Also, it's not built on top of Webauthn but kind-of reinvents the wheel as well (at least for {T,H}OTP it seems to use a library called pyotp).

I hope your implementation is either based on or ends up in a reusable solution rather than what PyPI did.

@nijel
Copy link
Member Author

nijel commented May 10, 2021

django-mfa2 actually looks quite good

Unfortunately, it does not. Based on quick look inside:

  • It comes with no tests
  • The code base looks ugly and contains no comments
  • It uses third-party JSONField instead of using native from Django, these days it would be more reasonable to use native one
  • It links two-factor model by username instead of using a foreign key

@TheAssassin
Copy link

That's a pity. Missing tests is one thing, but then also hard-to-maintain code... and there's obviously no excuses for violating database best practices.

Perhaps it's time for a proper Django webauthn module? I'm unfortunately not at all into Django...

@nijel
Copy link
Member Author

nijel commented Jan 20, 2022

Some months later, I did another look into available libraries and found few ones which were not mentioned before:

At least kagi and django-two-factor-auth seem promising now, and we should look into them in more depth.

@Maddy0027
Copy link
Contributor

@nijel how about we use pyotp libraries and for fallback option we genrate one time passwords and prompt user to save them in case he dosent have or lost 2fa device

@nijel
Copy link
Member Author

nijel commented Mar 20, 2024

We definitely want WebAuthn support as well, that's why I've listed suitable integrations above. They also provide Django integration to make implementation easier.

@Maddy0027
Copy link
Contributor

Maddy0027 commented Mar 20, 2024

otp.pdf
@nijel check this if it is ok

@nijel
Copy link
Member Author

nijel commented Mar 24, 2024

Why do you focus on pyotp? It doesn't address WebAuthn part. It doesn't have Django integration. I think one of the above referenced libraries will be a better approach than implementing everything again.

Ensuring that user can only attempt to login 5 time in every minute this will to
Stop brute force attacks

This is already present: https://docs.weblate.org/en/latest/admin/optionals.html#rate-limit

Implementation of TOTP code transmission mechanisms, including
email and SMS delivery, ensuring secure transmission and user-friendly setup
instructions.

We're not really interested in obscure TOTP delivery. The only thing that makes sense to implement is TOTP with application on the user side.

PS: This looks like a GSoC submission, are you aware that Weblate doesn't participate in that?

@Maddy0027
Copy link
Contributor

ok i will work using https://github.com/jazzband/django-two-factor-auth. And i know we are not part of gsoc but i am working or similar problem for gsoc but weblate is my first open sourece library that i am part of so i thought why not add this feature to weblate

@nijel
Copy link
Member Author

nijel commented Apr 2, 2024

2FA is quite a complex topic for a first contribution, but if you want to give it try, you're welcome. Before actually implementing anything, please post here a summary of changes you're going to make so that we can review the 2FA flow before.

@Maddy0027
Copy link
Contributor

@nijel can you just show me location of email server and database where user personal information is stored

@nijel
Copy link
Member Author

nijel commented Apr 2, 2024

@nijel nijel mentioned this issue Apr 3, 2024
@nijel nijel added this to the 5.7 milestone Apr 3, 2024
@nijel
Copy link
Member Author

nijel commented Jul 8, 2024

Finally, I'm about to implement this. There is still one major decision to be made - choose an actual implementation.

I've ruled out the following:

In the end, I ended up with two choices:

I currently see django-allauth as a better way in the long term as it would allow me to stop caring about python-social-auth, but there are many challenges, and I'm investigating if switching authentication library is something feasible now.

@raphaelm
Copy link

raphaelm commented Jul 8, 2024

For pretix, we settled on implementing the upper layers ourselves based on the packages django-otp and webauthn which I'm quite happy with as it allows us more flexibility than the everything-ready packages, but that's probably a matter of taste

@nijel
Copy link
Member Author

nijel commented Jul 8, 2024

Indeed, using django-allauth would bring some challenges, as they cover a lot of functionality we have already implemented in Weblate. As expected, they have chosen different approaches often and that's why I'm looking whether the move is actually viable for us. Starting now, I think django-allauth would be clearly a better choice for what we need, but years ago a different approach has been taken.

@nijel
Copy link
Member Author

nijel commented Jul 12, 2024

Okay, while it would be nice to rebase to a better maintained library, I see too many obstacles in that direction. So let's stick with python-social-auth and build two-factor auth on the current code-base.

nijel added a commit to nijel/weblate that referenced this issue Aug 1, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 2, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 3, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 4, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 5, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 5, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
nijel added a commit to nijel/weblate that referenced this issue Aug 5, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
@nijel nijel self-assigned this Aug 5, 2024
nijel added a commit to nijel/weblate that referenced this issue Aug 6, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
@nijel
Copy link
Member Author

nijel commented Aug 6, 2024

In the end, I've used django_otp and django_otp_webauthn instead of two_factor which turned out to be too opinionated for us, and we would have to reimplement most of it. The pull request is now being reviewed at #12173

nijel added a commit to nijel/weblate that referenced this issue Aug 8, 2024
- Implemented using django-otp and django-otp-webauthn
- Support for TOTP, WebAuthn and recovery codes

Fixes WeblateOrg#1681
@nijel nijel closed this as completed in 69d534f Aug 8, 2024
Copy link

github-actions bot commented Aug 8, 2024

Thank you for your report; the issue you have reported has just been fixed.

  • In case you see a problem with the fix, please comment on this issue.
  • In case you see a similar problem, please open a separate issue.
  • If you are happy with the outcome, don’t hesitate to support Weblate by making a donation.

1 similar comment
Copy link

github-actions bot commented Aug 8, 2024

Thank you for your report; the issue you have reported has just been fixed.

  • In case you see a problem with the fix, please comment on this issue.
  • In case you see a similar problem, please open a separate issue.
  • If you are happy with the outcome, don’t hesitate to support Weblate by making a donation.

@Korb
Copy link

Korb commented Aug 9, 2024

Should the corresponding option already appear in https://hosted.weblate.org/accounts/profile/#account?

@nijel
Copy link
Member Author

nijel commented Aug 9, 2024

Not yet, will be probably deployed later today together with #12200.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog This is not on the Weblate roadmap for now. Can be prioritized by sponsorship. enhancement Adding or requesting a new feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants