Django integration with Active Directory

Recently I was working on an in house project for an internal employee portal. We chose to implement this new web service in Django and deploy it on a Red Hat instance. Django by default comes with its own authentication and authorization libraries but in this case we wanted to integrate with our existing Active Directory service. Fortunately, AD supports LDAP (Lightweight Directory Access Protocol). By using the Python LDAP library we were able to integrate it with our SSO solution.

The documentation for the Django authentication backend is here but the modifications I specifically used for Microsoft Active Directory are specified below

To set this up, ensure the Django environment has the LDAP libraries installed.

pip install python-ldap
pip install D-auth-ldap

In settings.py import the LDAP libraries.

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType

You’ll need to specify LDAP as an authentication backend. Furthermore, if you want to assign permissions to individual users or add users to groups in Django, you’ll need to also install the Django model backed as well.

#In settings.py
import ldap

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

In your django app settings.py file, set the following variables.


#for a host of ldap.example.com
AUTH_LDAP_SERVER_URI - 'ldap://ldap.example.com
AUTH_LDAP_BIND_DN = 'CN=ldap_user,cn=Users,dc=example,dc=com'
# For instace
# AUTH_LDAP_BIND_DN = 'CN=ldap_user,cn=Users,dc=company,dc=local'

# If you using password authentication with ldap, specify it with this settings
AUTH_LDAP_BIND_PASSWORD = 'password'

Then you will need to specify the parameters for the LDAP user search when a user logs into the web service using Active directory credentials.

#For a domain of example.com
AUTH_LDAP_USER_SEARCH = LDAPSearch(
'dc=example,dc=com',ldap.SCOPE_SUBTREE,
'sAMAccountName=$(user)s'

The sAMAccountName will be mapped to the user variable that is set during login.

Next the ldap return values need to be mapped to fields in the Django user model. This is done with a dictionary specifying the django user object fields as keys and the LDAP field names as values.


AUTH_LDAP_USER_ATTR_MAP = {
 'username':'sAMAccountName',
'first_name': 'givenName',
'last_name': 'sn',
'email': 'mail',
#other fields as needed

}
# To ensure user object is updated each time on login
AUTH_LDAP_ALWAYS_UPDATE_USER = True

You may decide to create your own user object if you want to define other fields that aren’t included with the Django default user object. This can be done by declaring a new model that inherits the AbstractUser class. So in your models.py specify the following:

from django.contrib.auth.models import AbstractUser

class DerivedUser(AbstractUser):
    #Define additional user fields here

Once you define a new user model, you will need to register it as the user model in your settings.py file

AUTH_USER_MODEL = '<app name>.<user class>'
# For instance WebApp.DerivedUser

You may also want to map Active Directory group memberships to user permissions in your django application. You’ll need to specify the type of group object returned by the LDAP search as well as the group search parameters in the settings.py file.

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
'ou=_groups,dc=example,dc=com', ldap.SCOPE_SUBTREE
,"(objectClass=group)"
)

Then map django permissions to a user’s groups.

AUTH_LDAP_USER_FLAGS_BY_GROUP = {
'is_staff': 'CN=example_group,OU=_groups,DC=example,DC=com',
)

Also if you want to require group membership before they can authenticate at all then specify a require group membership setting.

from django_auth_ldap.config import LDAPGroupQuery
AUTH_LDAP_REQUIRE_GROUP = (
LDAPGroupQuery('cn=group1,ou_groups,dc=example,dc=com'),
)
#You can also supply deny groups with the ~ before the group query. 

For more information on groups check out.

https://django-auth-ldap.readthedocs.io/en/latest/groups.html