Created
November 18, 2014 22:54
-
-
Save acatejr/7af040add1361bfb4464 to your computer and use it in GitHub Desktop.
Active Directory authentication for Django
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.contrib.auth.models import User | |
import ldap | |
import logging | |
class ActiveDirectoryBackend: | |
def __init__(self): | |
# LDAP server | |
self.ldap_server = "[server name here]" | |
# Base directory name | |
self.base_dn = '[base dn here]' | |
# Set user attributes returned from ldap queries | |
# ['memberOf', 'userPrincipalName'] | |
self.attrs = ['displayName', 'company', 'mail', 'userPrincipalName'] | |
self.who = "[user name here]" | |
self.creds = "[password here]" | |
# Get an instance of a logger | |
self.logger = logging.getLogger(__name__) | |
def get_ldap_user(self, user_id): | |
""" | |
Finding a user results in a list of user attributes. | |
If user is not found in ldap then resulting list is empty. | |
""" | |
l = ldap.initialize(self.ldap_server) | |
l.simple_bind_s(self.who, self.creds) | |
l.protocol_version = ldap.VERSION3 | |
l.set_option(ldap.OPT_REFERRALS, 0) | |
l.set_option(ldap.OPT_SIZELIMIT, 5) | |
criteria = "(&(objectClass=user)(samaccountname=%s))" % user_id | |
results = l.search_s(self.base_dn, ldap.SCOPE_SUBTREE, criteria, self.attrs) | |
# Build a usable dictionary of the results | |
results = [entry for dn, entry in results if isinstance(entry, dict)] | |
return results | |
def authenticate(self, username=None, password=None): | |
user = None | |
ldap_user = self.get_ldap_user(username) | |
if not ldap_user: | |
return None | |
else: | |
# User is in ldap. Is user in app db | |
user = User.objects.filter(username=username) | |
if not user: | |
if ldap_user[0]['userPrincipalName'][0]: | |
email = ldap_user[0]['userPrincipalName'][0].strip() | |
else: | |
email = '' | |
user = User(username=username, email=email) | |
user.save() | |
else: | |
user = User.objects.get(username=username) | |
try: | |
if self.check_password(username, password): | |
return user | |
else: | |
return None | |
except User.DoesNotExist: | |
return None | |
def get_user(self, user_id): | |
ldap_user = self.get_ldap_user(user_id) | |
try: | |
return User.objects.get(pk=user_id) | |
except User.DoesNotExist: | |
return None | |
def check_password(self, username, password): | |
result = False | |
ldap_client = None | |
try: | |
# build a client | |
ldap_client = ldap.initialize(self.ldap_server) | |
# perform a synchronous bind | |
ldap_client.set_option(ldap.OPT_REFERRALS,0) | |
user = "%s@[host name here]" % username | |
ldap_client.simple_bind_s(user, password) | |
ldap_client.unbind() | |
result = True | |
except ldap.INVALID_CREDENTIALS: | |
self.logger.error('Wrong username and/or password.') | |
ldap_client.unbind() | |
result = False | |
except ldap.SERVER_DOWN: | |
self.logger.se('ActiveDirectory server not available.') | |
ldap_client.unbind() | |
result = False | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment