diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index 134d7b59d7..d242db232d 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -57,7 +57,7 @@ from zproject.backends import ZulipDummyBackend, EmailAuthBackend, \ ZulipLDAPUserPopulator, DevAuthBackend, GitHubAuthBackend, ZulipAuthMixin, \ dev_auth_enabled, password_auth_enabled, github_auth_enabled, \ require_email_format_usernames, AUTH_BACKEND_NAME_MAP, \ - ZulipLDAPConfigurationError + ZulipLDAPConfigurationError, ZulipLDAPExceptionOutsideDomain from zerver.views.auth import (maybe_send_to_registration, login_or_register_remote_user, @@ -2177,6 +2177,23 @@ class TestLDAP(ZulipTestCase): assert(user_profile is not None) self.assertEqual(user_profile.email, self.example_email("hamlet")) + @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) + def test_login_success_with_username(self) -> None: + self.mock_ldap.directory = { + 'uid=hamlet,ou=users,dc=zulip,dc=com': { + 'userPassword': 'testing' + } + } + with self.settings( + LDAP_APPEND_DOMAIN='zulip.com', + AUTH_LDAP_BIND_PASSWORD='', + AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=users,dc=zulip,dc=com'): + user_profile = self.backend.authenticate("hamlet", 'testing', + realm=get_realm('zulip')) + + assert(user_profile is not None) + self.assertEqual(user_profile.email, self.example_email("hamlet")) + @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) def test_login_success_with_email_attr(self) -> None: self.mock_ldap.directory = { @@ -2231,12 +2248,28 @@ class TestLDAP(ZulipTestCase): self.assertTrue(backend.get_group_permissions(None, None) == set()) @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) - def test_django_to_ldap_username(self) -> None: + def test_django_to_ldap_username_without_append_domain(self) -> None: + backend = self.backend + username = backend.django_to_ldap_username('"hamlet@test"@zulip.com') + self.assertEqual(username, '"hamlet@test"@zulip.com') + + @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) + def test_django_to_ldap_username_with_append_domain(self) -> None: backend = self.backend with self.settings(LDAP_APPEND_DOMAIN='zulip.com'): username = backend.django_to_ldap_username('"hamlet@test"@zulip.com') self.assertEqual(username, '"hamlet@test"') + username = backend.django_to_ldap_username('"hamlet@test"@zulip') + self.assertEqual(username, '"hamlet@test"@zulip') + + @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) + def test_django_to_ldap_username_with_invalid_domain(self) -> None: + backend = self.backend + with self.settings(LDAP_APPEND_DOMAIN='zulip.com'), \ + self.assertRaises(ZulipLDAPExceptionOutsideDomain): + backend.django_to_ldap_username('"hamlet@test"@test.com') + @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) def test_ldap_to_django_username(self) -> None: backend = self.backend diff --git a/zproject/backends.py b/zproject/backends.py index 83c30d6f73..999e7016ed 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -220,6 +220,13 @@ class ZulipRemoteUserBackend(RemoteUserBackend): email = remote_user_to_email(remote_user) return common_get_active_user(email, realm, return_data=return_data) +def is_valid_email(email: str) -> bool: + try: + validate_email(email) + except ValidationError: + return False + return True + def email_belongs_to_ldap(realm: Realm, email: str) -> bool: if not ldap_auth_enabled(realm): return False @@ -287,10 +294,11 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): def django_to_ldap_username(self, username: str) -> str: if settings.LDAP_APPEND_DOMAIN: - if not username.endswith("@" + settings.LDAP_APPEND_DOMAIN): - raise ZulipLDAPExceptionOutsideDomain("Email %s does not match LDAP domain %s." % ( - username, settings.LDAP_APPEND_DOMAIN)) - return email_to_username(username) + if is_valid_email(username): + if not username.endswith("@" + settings.LDAP_APPEND_DOMAIN): + raise ZulipLDAPExceptionOutsideDomain("Email %s does not match LDAP domain %s." % ( + username, settings.LDAP_APPEND_DOMAIN)) + return email_to_username(username) return username def ldap_to_django_username(self, username: str) -> str: