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