mirror of https://github.com/zulip/zulip.git
backends.py: Enable auth with any ldap attributes as username.
This commit enables user to authenticate with any attribute set in AUTH_LDAP_USER_SEARCH given that LDAP_EMAIL_ATTR is set to an email attributes in the ldap server. Thus email and username can be completely unrelated. With some tweaks by tabbott to squash in the documentation and make it work on older servers.
This commit is contained in:
parent
fb39e884c8
commit
28beddfd76
|
@ -1896,6 +1896,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_email_attr(self):
|
||||
# type: () -> None
|
||||
self.mock_ldap.directory = {
|
||||
'uid=letham,ou=users,dc=zulip,dc=com': {
|
||||
'userPassword': 'testing',
|
||||
'email': ['hamlet@zulip.com'],
|
||||
}
|
||||
}
|
||||
with self.settings(LDAP_EMAIL_ATTR='email',
|
||||
AUTH_LDAP_BIND_PASSWORD='',
|
||||
AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=users,dc=zulip,dc=com'):
|
||||
user_profile = self.backend.authenticate("letham", 'testing')
|
||||
|
||||
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_failure_due_to_wrong_password(self):
|
||||
# type: () -> None
|
||||
|
@ -2023,6 +2040,19 @@ class TestLDAP(ZulipTestCase):
|
|||
with self.assertRaisesRegex(Exception, 'Realm is None'):
|
||||
backend.get_or_create_user(email, _LDAPUser())
|
||||
|
||||
@override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',))
|
||||
def test_get_or_create_user_when_ldap_has_no_email_attr(self):
|
||||
# type: () -> None
|
||||
class _LDAPUser(object):
|
||||
attrs = {'fn': ['Full Name'], 'sn': ['Short Name']}
|
||||
|
||||
nonexisting_attr = 'email'
|
||||
with self.settings(LDAP_EMAIL_ATTR=nonexisting_attr):
|
||||
backend = self.backend
|
||||
email = 'nonexisting@zulip.com'
|
||||
with self.assertRaisesRegex(Exception, 'LDAP user doesn\'t have the needed email attribute'):
|
||||
backend.get_or_create_user(email, _LDAPUser())
|
||||
|
||||
@override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',))
|
||||
def test_django_to_ldap_username_when_domain_does_not_match(self):
|
||||
# type: () -> None
|
||||
|
|
|
@ -416,7 +416,7 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase):
|
|||
try:
|
||||
if settings.REALMS_HAVE_SUBDOMAINS:
|
||||
self._realm = get_realm(realm_subdomain)
|
||||
else:
|
||||
elif settings.LDAP_EMAIL_ATTR is not None:
|
||||
self._realm = get_realm_by_email_domain(username)
|
||||
username = self.django_to_ldap_username(username)
|
||||
user_profile = ZulipLDAPAuthBackendBase.authenticate(self, username, password)
|
||||
|
@ -433,6 +433,14 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase):
|
|||
def get_or_create_user(self, username, ldap_user):
|
||||
# type: (str, _LDAPUser) -> Tuple[UserProfile, bool]
|
||||
try:
|
||||
if settings.LDAP_EMAIL_ATTR is not None:
|
||||
# Get email from ldap attributes.
|
||||
if settings.LDAP_EMAIL_ATTR not in ldap_user.attrs:
|
||||
raise ZulipLDAPException("LDAP user doesn't have the needed %s attribute" % (settings.LDAP_EMAIL_ATTR,))
|
||||
|
||||
username = ldap_user.attrs[settings.LDAP_EMAIL_ATTR][0]
|
||||
self._realm = get_realm_by_email_domain(username)
|
||||
|
||||
user_profile = get_user_profile_by_email(username)
|
||||
if not user_profile.is_active or user_profile.realm.deactivated:
|
||||
raise ZulipLDAPException("Realm has been deactivated")
|
||||
|
|
|
@ -313,11 +313,10 @@ EMAIL_GATEWAY_IMAP_FOLDER = "INBOX"
|
|||
# * Fill in the LDAP configuration options below so that Zulip can
|
||||
# connect to your LDAP server
|
||||
#
|
||||
# * Setup the mapping between email addresses (used as login names in
|
||||
# Zulip) and LDAP usernames. There are two supported ways to setup
|
||||
# the username mapping:
|
||||
# * Setup the mapping between LDAP attributes and Zulip.
|
||||
# There are three supported ways to setup the username and/or email mapping:
|
||||
#
|
||||
# (A) If users' email addresses are in LDAP, set
|
||||
# (A) If users' email addresses are in LDAP and used as username, set
|
||||
# LDAP_APPEND_DOMAIN = None
|
||||
# AUTH_LDAP_USER_SEARCH to lookup users by email address
|
||||
#
|
||||
|
@ -326,6 +325,12 @@ EMAIL_GATEWAY_IMAP_FOLDER = "INBOX"
|
|||
# LDAP_APPEND_DOMAIN = example.com and
|
||||
# AUTH_LDAP_USER_SEARCH to lookup users by username
|
||||
#
|
||||
# (C) If LDAP username are completely unrelated to email addresses,
|
||||
# you should set:
|
||||
# LDAP_EMAIL_ATTR = "email"
|
||||
# LDAP_APPEND_DOMAIN = None
|
||||
# AUTH_LDAP_USER_SEARCH to lookup users by username
|
||||
#
|
||||
# You can quickly test whether your configuration works by running:
|
||||
# ./manage.py query_ldap username@example.com
|
||||
# From the root of your Zulip installation; if your configuration is working
|
||||
|
@ -365,6 +370,10 @@ AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=example,dc=com",
|
|||
# address, specify the domain to append here.
|
||||
LDAP_APPEND_DOMAIN = None # type: Optional[str]
|
||||
|
||||
# If username and email are two different LDAP attributes, specify the
|
||||
# attribute to get the user's email address from LDAP here.
|
||||
LDAP_EMAIL_ATTR = None # type: Optional[str]
|
||||
|
||||
# This map defines how to populate attributes of a Zulip user from LDAP.
|
||||
AUTH_LDAP_USER_ATTR_MAP = {
|
||||
# Populate the Django user's name from the LDAP directory.
|
||||
|
|
|
@ -169,6 +169,7 @@ DEFAULT_SETTINGS = {'TWITTER_CONSUMER_KEY': '',
|
|||
'ENABLE_GRAVATAR': True,
|
||||
'DEFAULT_AVATAR_URI': '/static/images/default-avatar.png',
|
||||
'AUTH_LDAP_SERVER_URI': "",
|
||||
'LDAP_EMAIL_ATTR': None,
|
||||
'EXTERNAL_URI_SCHEME': "https://",
|
||||
'ZULIP_COM': False,
|
||||
'SHOW_OSS_ANNOUNCEMENT': False,
|
||||
|
|
Loading…
Reference in New Issue