mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 20:44:04 +00:00
auth: Use zxcvbn to ensure password strength on server side.
For a long time, we've been only doing the zxcvbn password strength checks on the browser, which is helpful, but means users could through hackery (or a bug in the frontend validation code) manage to set a too-weak password. We fix this by running our password strength validation on the backend as well, using python-zxcvbn. In theory, a bug in python-zxcvbn could result in it producing a different opinion than the frontend version; if so, it'd be a pretty bad bug in the library, and hopefully we'd hear about it from users, report upstream, and get it fixed that way. Alternatively, we can switch to shelling out to node like we do for KaTeX. Fixes #6880.
This commit is contained in:
committed by
Tim Abbott
parent
0c2cc41d2e
commit
06c2161f7e
@@ -45,7 +45,7 @@ from zerver.lib.test_classes import (
|
||||
from zerver.models import \
|
||||
get_realm, email_to_username, CustomProfileField, CustomProfileFieldValue, \
|
||||
UserProfile, PreregistrationUser, Realm, RealmDomain, get_user, MultiuseInvite, \
|
||||
clear_supported_auth_backends_cache
|
||||
clear_supported_auth_backends_cache, PasswordTooWeakError
|
||||
from zerver.signals import JUST_CREATED_THRESHOLD
|
||||
|
||||
from confirmation.models import Confirmation, create_confirmation_link
|
||||
@@ -58,7 +58,7 @@ from zproject.backends import ZulipDummyBackend, EmailAuthBackend, \
|
||||
ZulipLDAPConfigurationError, ZulipLDAPExceptionNoMatchingLDAPUser, ZulipLDAPExceptionOutsideDomain, \
|
||||
ZulipLDAPException, query_ldap, sync_user_from_ldap, SocialAuthMixin, \
|
||||
PopulateUserLDAPError, SAMLAuthBackend, saml_auth_enabled, email_belongs_to_ldap, \
|
||||
get_social_backend_dicts, AzureADAuthBackend
|
||||
get_social_backend_dicts, AzureADAuthBackend, check_password_strength
|
||||
|
||||
from zerver.views.auth import (maybe_send_to_registration,
|
||||
_subdomain_token_salt)
|
||||
@@ -226,7 +226,12 @@ class AuthBackendTest(ZulipTestCase):
|
||||
|
||||
# Now do the same test with the empty string as the password.
|
||||
password = ""
|
||||
user_profile.set_password(password)
|
||||
with self.assertRaises(PasswordTooWeakError):
|
||||
# UserProfile.set_password protects against setting an empty password.
|
||||
user_profile.set_password(password)
|
||||
# We do want to force an empty password for this test, so we bypass the protection
|
||||
# by using Django's version of this method.
|
||||
super(UserProfile, user_profile).set_password(password)
|
||||
user_profile.save()
|
||||
self.assertIsNone(EmailAuthBackend().authenticate(username=self.example_email('hamlet'),
|
||||
password=password,
|
||||
@@ -475,6 +480,20 @@ class AuthBackendTest(ZulipTestCase):
|
||||
httpretty.disable()
|
||||
httpretty.reset()
|
||||
|
||||
class CheckPasswordStrengthTest(ZulipTestCase):
|
||||
def test_check_password_strength(self) -> None:
|
||||
with self.settings(PASSWORD_MIN_LENGTH=0, PASSWORD_MIN_GUESSES=0):
|
||||
# Never allow empty password.
|
||||
self.assertFalse(check_password_strength(''))
|
||||
|
||||
with self.settings(PASSWORD_MIN_LENGTH=6, PASSWORD_MIN_GUESSES=1000):
|
||||
self.assertFalse(check_password_strength(''))
|
||||
self.assertFalse(check_password_strength('short'))
|
||||
# Long enough, but too easy:
|
||||
self.assertFalse(check_password_strength('longer'))
|
||||
# Good password:
|
||||
self.assertTrue(check_password_strength('f657gdGGk9'))
|
||||
|
||||
class SocialAuthBase(ZulipTestCase):
|
||||
"""This is a base class for testing social-auth backends. These
|
||||
methods are often overriden by subclasses:
|
||||
@@ -832,6 +851,8 @@ class SocialAuthBase(ZulipTestCase):
|
||||
self.assert_logged_in_user_id(user_profile.id)
|
||||
self.assertEqual(user_profile.full_name, expected_final_name)
|
||||
|
||||
self.assertFalse(user_profile.has_usable_password())
|
||||
|
||||
@override_settings(TERMS_OF_SERVICE=None)
|
||||
def test_social_auth_registration(self) -> None:
|
||||
"""If the user doesn't exist yet, social auth can be used to register an account"""
|
||||
|
||||
Reference in New Issue
Block a user