0

Problem

As far as I can tell, django-auth-ldap is doing everything I need given my configuration. Except that it's unable to establish a mapping from ldap groups to django groups.

I have a group in ldap called dev, i.e., cn=dev. I also have a group in django called dev. When I login with my user in Django (uid=fkilibarda), django-auth-ldap is able to get my firstname, lastname, and email, but it fails to add me to the dev group.

Debugging

django_auth_ldap.backend line: 203

def get_group_permissions(self, user, obj=None):                            
   if not hasattr(user, 'ldap_user') and self.settings.AUTHORIZE_ALL_USERS:
       _LDAPUser(self, user=user)  # This sets user.ldap_user              

   if hasattr(user, 'ldap_user') and (user.ldap_user.dn is not None):      
       return user.ldap_user.get_group_permissions()                       
   else:                                                                   
       return set()

I've found that hasattr(user, 'ldap_user') is always false. Thus, user.ldap_user.get_group_permissions() never runs, which is why the group mapping is never established.

I just don't understand the significance of the above. Why doesn't user have the ldap_user attribute?

Configuration

MIDDLEWARE = [
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = {
    'django_auth_ldap.backend.LDAPBackend',
    'django.contrib.auth.backends.ModelBackend',
}

# ===================
# LDAP configurations
# ===================

AUTH_LDAP_SERVER_URI = "example_server"

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    'ou=group,dc=example,dc=example,dc=com',
    ldap.SCOPE_SUBTREE,
    '(objectClass=posixGroup)',
) 
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()

AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    'is_active': 'cn=dev,ou=group,dc=example,dc=example,dc=com',
    'is_staff': 'cn=dev,ou=group,dc=example,dc=example,dc=com',
    'is_superuser': 'cn=dev,ou=group,dc=example,dc=example,dc=com',
}

AUTH_LDAP_USER_SEARCH = LDAPSearch(
    'ou=people,dc=example,dc=example,dc=com',
    ldap.SCOPE_SUBTREE,
    '(uid=%(user)s)'
)

AUTH_LDAP_USER_ATTR_MAP = {
    "first_name": "givenName", 
    "last_name": "sn", 
    "email": "mail"
}

AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_ALWAYS_UPDATE_USER = True

Version

django-auth-ldap==1.2.14 python3

Filip Kilibarda
  • 2,484
  • 2
  • 20
  • 31
  • If hasattr(user, 'ldap_user') is False, then it sounds like this particular User was not authenticated by LDAPBackend. Do you have multiple AUTHENTICATION_BACKENDS configured? – psagers Oct 31 '17 at 20:45
  • Hi, thanks for looking into it. I added additional information to the *configuration* section above showing AUTHENTICATION_BACKENDS. – Filip Kilibarda Oct 31 '17 at 21:14
  • @psagers ^^^^^^^^ – Filip Kilibarda Oct 31 '17 at 21:22
  • Check user.backend (https://docs.djangoproject.com/en/1.11/topics/auth/default/#selecting-the-authentication-backend) to see which backend ultimately authenticated the user. It sounds like LDAPBackend is failing and it's falling back to ModelBackend. Can also try disabling ModelBackend or setting AUTH_LDAP_AUTHORIZE_ALL_USERS to triangulate. Logging (https://django-auth-ldap.readthedocs.io/en/1.2.x/logging.html) is also generally helpful. – psagers Oct 31 '17 at 21:26
  • @psagers I took some time to read about how sessions/users/authentication in hope of getting a better understanding of this. I also added a `hasattr(user, 'backend')` to `django_auth_ldap.backend::LDAPBackend::get_group_permissions` and it always returns `False` when I login through the django admin interface. So I'm not sure how to see which backend my user was authenticated with. – Filip Kilibarda Oct 31 '17 at 22:30
  • @psagers I disabled ModelBackend and it didn't seem to change anything. – Filip Kilibarda Oct 31 '17 at 22:35
  • @psagers Setting `AUTH_LDAP_AUTHORIZE_ALL_USERS = True` has made it such that `hasattr(user, 'ldap_user')` now returns `True`, however, it's still not mapping LDAP groups to django groups. Will look into it a bit more. – Filip Kilibarda Oct 31 '17 at 22:42
  • @psagers Looks like I just miss understood how it all works. I assumed that it would add users to the appropriate groups in django. So if I'm a member of the `dev` group in LDAP, then `django_auth_ldap` would add my user to the `dev` group in django, and get the permissions from there. Turns out the permissions have been working just fine the whole time -- I just needed to log in with a test user. Thanks for the help! – Filip Kilibarda Nov 01 '17 at 00:27

1 Answers1

2

Turns out I miss understood how django_auth_ldap works. I expected, that when AUTH_LDAP_FIND_GROUP_PERMS = True, my user would be added to the appropriate group in Django, based on my group membership in LDAP.

So if user fkilibarda were a member of the dev group in LDAP, then I thought the user fkilibarda would be added to the dev group in Django automatically.

Instead, for every request that a user makes in Django, django_auth_ldap will send a request to LDAP to figure out what group/permissions the user should get. This is clearly the better approach...

So if you're testing this:

  1. Don't expect users to be added to groups in Django.
  2. Don't use a superuser when testing this because the superuser has access to everything.

The django_auth_ldap documentation describes this quite clearly actually

Filip Kilibarda
  • 2,484
  • 2
  • 20
  • 31