Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with custom Authentication Backend for Django

I'm having a problem with a custom Authentication Backend I've built for an Active Directory via LDAP authentication.

The problem is that from the admin login page, after it properly authenticates and creates the new user in the database (or updates their info from the LDAP server), but then returns me to the admin login page indicating that I failed to enter a valid username and password.

Considering it authenticates and creates/updates the user in the django database, what am I doing wrong?

The code:

import ldap
import re
from django.conf import ad_settings
grps = re.compile(r'CN=(\w+)').findall

def anyof(short_group_list, adu):
    all_groups_of_user = set(g for gs in adu.get('memberOf',()) for g in grps(gs))
    return any(g for g in short_group_list if g in all_groups_of_user)

class ActiveDirectoryBackend(ModelBackend):
    """
    This backend utilizes an ActiveDirectory server via LDAP to authenticate
    users, creating them in Django if they don't already exist.
    """

    def authenticate(self, username=None, password=None):
        con = None
        ldap.set_option(ldap.OPT_REFERRALS, 0)
        try:
            con = ldap.initialize('ldap://%s:%s' % (ad_settings.AD_DNS_NAME,
                  ad_settings.AD_LDAP_PORT))
            con.simple_bind_s(username+"@"+ad_settings.AD_DNS_NAME, password)
            ADUser = con.search_ext_s(ad_settings.AD_SEARCH_DN,
                                      ldap.SCOPE_SUBTREE,
                                      "sAMAccountName=%s" % username,
                                      ad_settings.AD_SEARCH_FIELDS)[0][1]
            con.unbind()
        except ldap.LDAPError:
            return None
        # Does user belong to appropriate AD group?
        if not anyof(ad_settings.PROJECTCODE,ADUser):
            return None

        # Does user already exist in Django?
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            #create Django user
            user = User(username=username, is_staff = True, is_superuser = False)
        #Update User info from AD
        if ADUser.has_key('givenName'):
            user.first_name = ADUser.get('givenName')[0]
        if ADUser.has_key('sn'):
            user.last_name = ADUser.get('sn')[0]
        if ADUser.has_key('mail'):
            user.email = ADUser.get('mail')[0]

        # Does not store password in Django.
        user.set_unusable_password()
        user.save()
        return user

EDIT: Figured out. Users cannot log in unless they are active (even though the documentation does not say that). Therefore, in the code given, the line that creates the new user should look like:

        user = User(username=username, is_staff = True, is_Active = True, 
                    is_superuser = False)
like image 987
Technical Bard Avatar asked Jul 09 '09 17:07

Technical Bard


People also ask

How do I authenticate a custom model in Django?

django authenticate() for custom user model It creates a new user correctly. But when I try to authenticate the user from shell or from views, the authenticate() function doesn't work for users having is_active=False . The above line returns nothing if the user is inactive but returns the user object otherwise.

How does Django implement custom authentication?

To implement a custom authentication scheme, we need to subclass the DRF's BaseAuthentication class and override the . authenticate(self, request) method. The method should return a two-tuple of (user, auth) if authentication succeeds, or None otherwise.

What is authentication backend in Django?

Authentication backends provide an extensible system for when a username and password stored with the user model need to be authenticated against a different service than Django's default. You can give your models custom permissions that can be checked through Django's authorization system.

Which method of authentication backend takes credentials in Django?

The authenticate method takes credentials as keyword arguments. Most of the time, it'll just look like this: class MyBackend(object): def authenticate(self, username=None, password=None): # Check the username/password and return a user. ...


1 Answers

Figured out. Users cannot log in unless they are active (even though the documentation does not say that). Therefore, in the code given, the line that creates the new user should look like:

    user = User(username=username, is_staff = True, is_Active = True, 
                is_superuser = False)
like image 130
Technical Bard Avatar answered Nov 15 '22 21:11

Technical Bard