signup: Prevent unauthorized signup for realms without EmailAuthBackend.

Zulip supports a configuration where account creation is limited solely
by being able to authenticate with a single-sign on authentication
backend, such as Google Authentication, SAML, or LDAP (i.e., the
organization places no restrictions on email address domains or
invitations being required to join, but has disabled the
EmailAuthBackend that is used for email/password authentication).

A bug in the Zulip server meant that Zulip allowed users to create an
account in such organizations by confirming their email address, without
having an account with the SSO authentication backend.

Co-authored-by: Tim Abbott <tabbott@zulip.com>
This commit is contained in:
Mateusz Mandera
2025-04-02 23:18:04 +08:00
committed by Tim Abbott
parent 2429157498
commit c4bb6509dd
3 changed files with 53 additions and 8 deletions

View File

@@ -1028,7 +1028,7 @@ class LoginTest(ZulipTestCase):
# to sending messages, such as getting the welcome bot, looking up
# the alert words for a realm, etc.
with (
self.assert_database_query_count(93),
self.assert_database_query_count(95),
self.assert_memcached_count(18),
self.captureOnCommitCallbacks(execute=True),
):
@@ -3147,6 +3147,39 @@ class UserSignUpTest(ZulipTestCase):
result = self.client_get("/register", subdomain="", follow=True)
self.assert_in_success_response(["Find your Zulip accounts"], result)
@override_settings(
AUTHENTICATION_BACKENDS=(
"zproject.backends.SAMLAuthBackend",
"zproject.backends.ZulipDummyBackend",
)
)
def test_cant_obtain_confirmation_email_when_email_backend_disabled(self) -> None:
"""
When a realm disables EmailAuthBackend while keeping invite_required set to False,
users must not be allowed to generate a confirmation email to themselves by POSTing
it to the registration endpoints - as that would allow them to sign up and obtain
a logged in session in the realm without actually having to go through the
allowed authentication methods.
"""
realm = get_realm("zulip")
self.assertEqual(realm.invite_required, False)
from django.core.mail import outbox
email = "newuser@zulip.com"
original_outbox_length = len(outbox)
result = self.client_post("/register/", {"email": email})
self.assert_not_in_success_response(["check your email"], result)
self.assert_in_success_response(["Sign up with"], result)
self.assertEqual(original_outbox_length, len(outbox))
result = self.client_post("/accounts/home/", {"email": email})
self.assert_not_in_success_response(["check your email"], result)
self.assert_in_success_response(["Sign up with"], result)
self.assertEqual(original_outbox_length, len(outbox))
@override_settings(
AUTHENTICATION_BACKENDS=(
"zproject.backends.ZulipLDAPAuthBackend",