Django: authenticating against remote LDAP user - simple example? Django: authenticating against remote LDAP user - simple example? django django

Django: authenticating against remote LDAP user - simple example?


In your python setting file add line

AUTHENTICATION_BACKENDS = (    'django_auth_ldap.backend.ActiveDirectoryGroupMembershipSSLBackend',    'django.contrib.auth.backends.ModelBackend')

Here is my code just replace it with your information. Save this file as backend.py Place the file into a folder called django_auth_ldap. Make sure the folder has the __init.py inside.

import ldap;from django.contrib.auth.models import User, Groupclass ActiveDirectoryGroupMembershipSSLBackend:    #Required parameters    AD_DNS_NAME ='your remote ldap server location';    AD_LDAP_PORT = 636    AD_LDAP_URL = 'ldaps://%s' % AD_DNS_NAME;    AD_SEARCH_DN = 'dc=bbc,dc=ad,dc=bcc,dc=net'; # this is your search dn    AD_NT4_DOMAIN = 'bbc.ad.bbc.net'; #its your ad domain    AD_SEARCH_FIELDS = ['mail','givenName','sn','sAMAccountName','memberOf'];    AD_MEMBERSHIP_REQ = ['Group_Required','Alternative_Group'];    AD_CERT_FILE = "C:/player/Python/Application/cert/mycert.cer";AD_DEBUG = False;AD_DEBUG_FILE ='';def authenticate(self,username=None,password=None):    try:        if len(password) == 0:            return None        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)        ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 2)        l = ldap.initialize(self.AD_LDAP_URL)        l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)        binddn = "%s@%s" % (username,self.AD_NT4_DOMAIN)        l.simple_bind_s(binddn,password)        l.unbind_s()        return self.get_or_create_user(username,password)    except ImportError:        pass    except ldap.INVALID_CREDENTIALS:        passdef get_or_create_user(self, username, password):    try:        user = User.objects.get(username=username)    except User.DoesNotExist:        try:        # debug info            debug=0            if len(self.AD_DEBUG_FILE) > 0:                if self.AD_DEBUG:                    debug = open(self.AD_DEBUG_FILE,'w')                    print >>debug, "create user %s" % username            ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,self.AD_CERT_FILE)            ldap.set_option(ldap.OPT_REFERRALS,0) # DO NOT TURN THIS OFF OR SEARCH WON'T WORK!                  # initialize            if debug:                print >>debug, 'ldap.initialize...'            l = ldap.initialize(self.AD_LDAP_URL)            l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)            # bind            if debug:                print >>debug, 'bind...'            binddn = "%s@%s" % (username,self.AD_NT4_DOMAIN)            l.bind_s(binddn,password)            # search            if debug:                print >>debug, 'search...'            result = l.search_ext_s(self.AD_SEARCH_DN,ldap.SCOPE_SUBTREE,"sAMAccountName=%s" % username,self.AD_SEARCH_FIELDS)[0][1]            if debug:                print >>debug, result            # Validate that they are a member of review board group            if result.has_key('memberOf'):                membership = result['memberOf']            else:                membership = None            if debug:                print >>debug, "required:%s" % self.AD_MEMBERSHIP_REQ            bValid=0            for req_group in self.AD_MEMBERSHIP_REQ:                if debug:                    print >>debug, "Check for %s group..." % req_group                for group in membership:                    group_str="CN=%s," % req_group                    if group.find(group_str) >= 0:                        if debug:                            print >>debug, "User authorized: group_str membership found!"                        bValid=1                        break            if bValid == 0:                if debug:                    print >>debug, "User not authorized, correct group membership not found!"                return None            # get email            if result.has_key('mail'):                mail = result['mail'][0]            else:                mail = None            if debug:                print >>debug, "mail=%s" % mail            # get surname            if result.has_key('sn'):                last_name = result['sn'][0]            else:                last_name = None            if debug:                print >>debug, "sn=%s" % last_name            # get display name            if result.has_key('givenName'):                first_name = result['givenName'][0]            else:                first_name = None            if debug:                print >>debug, "first_name=%s" % first_name            l.unbind_s()            user = User(username=username,first_name=first_name,last_name=last_name,email=mail)        except Exception, e:            if debug:                print >>debug, "exception caught!"                print >>debug, e            return None        user.is_staff = False        user.is_superuser = False        user.set_password('ldap authenticated')        user.save()        # add user to default group        group=Group.objects.get(pk=1)        if debug:            print >>debug, group        if debug:            print >>debug, "add %s to group %s" % (username,group)        user.groups.add(group)        user.save()        if debug:            print >>debug, "successful group add"        if debug:            debug.close()    return userdef get_user(self, user_id):    try:        return User.objects.get(pk=user_id)    except User.DoesNotExist:        return None


Are you trying to get some Single Sign On solution working for your MS Windows users?

Then you'll find all the hints you need in http://docs.djangoproject.com/en/dev/howto/auth-remote-user/


First, I would suggest to ask user to provide sAMAccountName (which is exact windows login name and usually 'firstName.lastName', also better for the user has multiple words in their name) rather than using just cn user name ('firstName lastName').

Below is my complete LDAPUserAuthBackend code and it is added intoAUTHENTICATION_BACKENDS

from django.contrib.auth.backends import RemoteUserBackendfrom django.contrib.auth.models import User, Permissionfrom django.conf import settingsimport ldapimport reimport logginglog = logging.getLogger(__name__)INTERNAL_USER = Noneclass LDAPUserAuthBackend(RemoteUserBackend):    create_unknown_user = False    def authenticate(self, username=None, password=None, **kwargs):        # if username or password is not given, then skip        if not username or not password:            return None        try:            # initialize connection to ActiveDirectory  the property contains ldap url like ldap://hostname:389            connect = ldap.initialize(settings.AUTH_LDAP_SERVER_URL)            # if user just provide account name portion 'fistName.lastName' on username            # then use your company default domain            if '\\' not in username:                connect.simple_bind_s(username + '@myCompanyDomain.com', password)                base_dn = 'cn=users,dc=myCompanyDomain,dc=com'                search_filter = '(&(objectClass=user)(sAMAccountName=' + username + '))'            else:                # if user provides domain info in username like 'myCompanyDomain\firstName.lastName'                domain,  account_name = username.split('\\')                connect.simple_bind_s('{user_name}@{domain_name}.com'.format(user_name=account_name, domain_name=domain), password)                base_dn = 'cn=users,dc={domain_name},dc=com,'.format(domain_name=domain)                search_filter = '(&(objectClass=user)(sAMAccountName=' + account_name + '))'                username = account_name            result = connect.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, ['memberOf'])            log.debug(result)            # if search result is found, result will be [(user_dn,{'memberOf':['group cn'...]}]            if result:                result_user_dn, result_dict = result[0]                groups = ','.join(result_dict.get('memberOf')).lower()                # check member is belong to the group                if result_user_dn:                    if settings.STAFF_USER_GROUP.lower() in groups or \                       settings.ADMIN_USER_GROUP.lower() in groups:                        user, created = User.objects.get_or_create(username=username)                        first_name, last_name = re.split('\.', username)                        user.first_name = first_name                        user.last_name = last_name                        user.is_active = True                        user.is_staff = True                        if settings.ADMIN_USER_GROUP.lower() in groups:                            user.is_superuser = True                        global INTERNAL_USER                        INTERNAL_USER = user                        return user            log.info('fail to authorize user, username: {}'.format(username))            return None        except ldap.LDAPError as e:            log.warning('authentication error, detail: {}'.format(str(e)))            return None        finally:            connect.unbind_s()    def get_user(self, user_id):        # don't want to go back to database.        # once auth via LDAP successful, that is the user        # because of the user_id is for user passed auth via this backend        global INTERNAL_USER        return INTERNAL_USER