Moteur LDAP

Paramètrage LDAP

# https://github.com/pyldap/pyldap/
import ldap

from django_auth_ldap.config import (
    # https://django-auth-ldap.readthedocs.io/en/latest/authentication.html
    LDAPSearch,
    LDAPSearchUnion,
    # https://django-auth-ldap.readthedocs.io/en/latest/groups.html
    GroupOfNamesType,
)

...

############# Authentification LDAP avec django-auth-ldap ##############
#
# https://django-auth-ldap.readthedocs.io/en/latest/
#
AUTH_LDAP_SERVER_URI = "ldap://XX.YYY.ZZZ"
# LDAP Search/Bind
AUTH_LDAP_BIND_DN = "cn=apache,cn=users,dc=int,dc=XXX,dc=eu"
AUTH_LDAP_BIND_PASSWORD = "#AAXXXYYYY"
AUTH_LDAP_USER_SEARCH = LDAPSearch(
    "ou=users,ou=XXX Technologies,dc=int,dc=XXX,dc=eu",
    ldap.SCOPE_SUBTREE,
    "(sAMAccountName=%(user)s)",
)
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    "OU=Groups,OU=XXX Technologies,DC=int,DC=XXX,DC=eu",
    ldap.SCOPE_SUBTREE,
    "(objectClass=group)",
)
# What to do once the user is authenticated
AUTH_LDAP_USER_ATTR_MAP = {
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mail",
}

########### Paramètrage Django pour l'utilisation de LDAP ##############
# https://docs.djangoproject.com/fr/2.1/ref/settings/#std:setting-AUTHENTICATION_BACKENDS
AUTHENTICATION_BACKENDS = (
    "django.contrib.auth.backends.ModelBackend",
    "accounts.backends.Id3LDAPBackend",
    "accounts.backends.Id3AuthBackend",
)

Un moteur LDAP accounts/backends.py

  1"""Définition des backends d'authentification.
  2
  3
  4.. seealso::
  5
  6   - https://docs.djangoproject.com/en/dev/topics/auth/customizing/#authentication-backends
  7   - https://docs.djangoproject.com/fr/1.10/topics/auth/customizing/#authentication-backends
  8   - https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.backends
  9
 10
 11
 12.. seealso::
 13
 14   - https://pythonhosted.org/django-auth-ldap/
 15   - https://bitbucket.org/psagers/django-auth-ldap/commits/tag/1.2.10
 16
 17
 18"""
 19import logging
 20
 21import django.contrib.auth
 22import django_auth_ldap
 23import structlog
 24from django.contrib.auth import get_backends
 25from django.contrib.auth import get_user_model
 26from django_auth_ldap.backend import LDAPBackend
 27from employes.models import Employe
 28
 29# https://pythonhosted.org/django-auth-ldap/
 30# https://docs.djangoproject.com/en/dev/ref/contrib/auth/#django.contrib.auth.backends.ModelBackend
 31# https://docs.djangoproject.com/en/1.10/_modules/django/contrib/auth/
 32
 33# from django.contrib.auth.backends import ModelBackend
 34
 35
 36logger = logging.getLogger("django_auth_ldap")
 37logger.addHandler(logging.StreamHandler())
 38logger.setLevel(logging.DEBUG)
 39
 40
 41class Id3LDAPBackend(django_auth_ldap.backend.LDAPBackend):
 42    """A custom LDAP authentication backend."""
 43
 44    def authenticate(self, request=None, username=None, password=None, **kwargs):
 45        """Overrides LDAPBackend.authenticate to save user password in django.
 46
 47        Changement de signature le 2017-06-20
 48
 49        -    def authenticate(self, username, password, **kwargs):
 50        +    def authenticate(self, request=None, username=None, password=None, **kwargs)
 51        """
 52
 53        logger.info(f"Id3LDAPBackend.authenticate({username})")
 54        user = None
 55        try:
 56            user = LDAPBackend.authenticate(
 57                self, username=username, password=password, request=request
 58            )
 59            logger.info(f"Found user:{user}")
 60            try:
 61                employe = Employe.objects.get(login=username)
 62                if employe.user is None:
 63                    try:
 64                        employe.user = user
 65                        employe.save()
 66                    except Exception as error:
 67                        logger.error(f"Can't save {employe}")
 68            except Exception as error:
 69                logger.error(f"Employe {username} not found:{error}")
 70
 71        except Exception as error:
 72            logger.info(
 73                f"Exception in Id3LDAPBackend.authenticate({username}) exception:{error}"
 74            )
 75
 76        # If user has successfully logged, save his password in django database
 77        if user:
 78            logger.info(f"Id3LDAPBackend.authenticate.set_password")
 79            user.set_password(password)
 80            logger.info(f"Id3LDAPBackend.authenticate() user.save()")
 81            user.save()
 82        else:
 83            logger.info("User is none")
 84
 85        return user
 86
 87    def get_or_create_user(self, username, ldap_user):
 88        """Overrides LDAPBackend.get_or_create_user to force from_ldap to True."""
 89
 90        logger.debug("Id3LDAPBackend.get_or_create_user()")
 91        kwargs = {"username": username, "defaults": {"from_ldap": True}}
 92        user_model = get_user_model()
 93        user = user_model.objects.get_or_create(**kwargs)
 94        logger.debug(f"Id3LDAPBackend.get_or_create_user({user})")
 95        return user
 96
 97
 98class Id3AuthBackend(django.contrib.auth.backends.ModelBackend):
 99    """A custom authentication backend overriding django ModelBackend."""
100
101    @staticmethod
102    def _is_ldap_backend_activated():
103        """Returns True if Id3LDAPBackend is activated."""
104        return Id3LDAPBackend in [b.__class__ for b in get_backends()]
105
106    def authenticate(self, username, password):
107        """Overrides ModelBackend to refuse LDAP users if Id3LDAPBackend is activated."""
108
109        if self._is_ldap_backend_activated():
110            user_model = get_user_model()
111            logger.debug(
112                f"Id3AuthBackend.authenticate({username}/{password}) get_user_model():{user_model}"
113            )
114            try:
115                user = user_model.objects.get(username=username, from_ldap=False)
116                logger.debug(
117                    f"Id3AuthBackend.authenticate({username}/{password}) user_model.objects.get({user})"
118                )
119                return user
120            except:
121                logger.debug("Id3AuthBackend.authenticate() return None")
122                return None
123        else:
124            logger.debug("Ldap backend is not activated")
125
126        return user