1

Could anyone of you please help me to implement LDAP authentication using Django. I want to develop a web application which should allow users to access the application post LDAP authentication. I have coded the basic things but I get some failures.

Settings.py

"""
Django settings for HandBook project.

Generated by 'django-admin startproject' using Django 2.1.7.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os
import ldap
from django_auth_ldap.config import LDAPSearch
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
AUTH_LDAP_SERVER_URI = "serverIp"
AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend')
AUTH_LDAP_CONNECTION_OPTIONS = {
    ldap.OPT_REFERRALS: 0
}
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '4xkkb*m!&@^xzhkpe6#gxe@xeee0ug3q0h$@-)#lv8+0dqpid*'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ["192.168.113.75"]


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'NewHandBook.apps.NewhandbookConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
]

ROOT_URLCONF = 'HandBook.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'HandBook.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

Views.py

from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.template import RequestContext
from django.shortcuts import render_to_response


def login(request):
    return render(request, 'login/login.html')


def login_user(request):
    username = password = ""
    state = ""

    if request.POST:
        username = request.POST.get('username')
        password = request.POST.get('password')

        print(username, password)

        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            return render(request, 'login/base.html', {'state': state, 'username': username})
        else:
            return render(request, 'login/login.html', {'state': state, 'username': username})
)

login.html

    {% extends 'login/base.html' %}
{% load static %}

<html>
<head>
    <title>Login</title>
</head>
<body>
{% block body %}
    <form method="post" action="/NewHandBook/validate/">{% csrf_token %}
        <div class="container">
            <div class="row">
                <div class="col-md-10 offset=md-1">
                    <div class="row">
                        <div class="col-md-5 register-left "><br><br>
                            <img style="width: 350px;position: absolute;margin-left: -350px;margin-top: -80px"
                                 src="{% static 'images/gar.png' %}">
                            <h1 style="font-family: Brush Script MT;font-size: 70px;margin-top: 45px;margin-left: -342px">
                                HandBook.</h1>
                            <p style="font-family: Courier New;margin-top: -20px;margin-left: -359px "><i
                                    class="fas fa-shield-alt"></i> Secure <i
                                    class="far fa-share-square"></i> Share <i class="far fa-smile-beam"></i> Smile
                            </p>

                        </div>

                        <div class="col-md-7 register-right">
                            <h2 style="font-family: Courier;color: azure">Login Here</h2>
                            <h7 style="font-family: Courier;font-size: 13px;color: aliceblue">
                                <h7 style="color: red">*</h7>
                                Please use your system credentials
                            </h7>
                            <div class="register-form">
                                <div class="form-group">
                                    <input type="text" name="username" class="form-control" placeholder="User name"
                                           style="font-family: Courier">

                                </div>
                                <div class="form-group">
                                    <input type="password" name="password" class="form-control" placeholder="Password"
                                           style="font-family: Courier">

                                </div>
                                <input type="reset" class="btn btn-primary" value="Reset">
                                <button type="submit" class="btn btn-primary"> Login Now</button>

                            </div>

                        </div>
                    </div>
                </div>
            </div>
        </div>
    </form>
{% endblock %}
</body>enter code here
</html>## Heading ##

I get below error when i run my project exception

Could anyone of you please help me here.

My use case: user should be able to land on some home page after a successful login or should land back on same login page if provided credentials are invalid.

vivek.p.n manu
  • 286
  • 1
  • 4
  • 19
  • Did you run `python manage.py makemigrations` and `python manage.py migrate`? – Max Mar 22 '19 at 10:11
  • Thanks Jonhy for your response. Yes !! I had run those above commands. Still, I'm getting ImportError at /NewHandBook/validate/ d doesn't look like a module path...... It will be very helpful if you can help me on this. – vivek.p.n manu Mar 22 '19 at 10:26
  • is /NewHandBook/validate/ `validate` python package? Or it's just a regular folder? or is it a python file? – Max Mar 22 '19 at 10:32
  • In my urls.py, I have just added an redirection to call the function. from django.conf.urls import url from . import views urlpatterns = [ url('login', views.login), url('validate',views.login_user) ] – vivek.p.n manu Mar 22 '19 at 10:36

2 Answers2

1

The error indicates that you are passing a single Python path where you should actually pass a list of Python paths, i.e. django.some.module.path instead of ['django.some.module.path']

Django then iterates over the string, and tries to import each character. In case of django.some.module.path, Django tries to import d, which gives you the error you are seeing.

To pinpoint the exact source of the error, you have to provide the complete traceback. You can click on 'Switch to copy-and-paste view' on the Debug Error page.

Update:

Here is your error:

AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend')

Single entry tuples need a comma, like this:

AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend',)
Daniel Hepper
  • 28,981
  • 10
  • 72
  • 75
  • Thanks for your response Daniel !!! Could you please tell me where i should be making the above changes. – vivek.p.n manu Mar 22 '19 at 11:00
  • The stacktrace you posted indicates that error is in the setting `AUTHENTICATION_BACKENDS`, but it is not listed in your `settings.py`. Is the `settings.py` you posted actually the one you are using? It doesn't contain any LDAP specific settings. – Daniel Hepper Mar 22 '19 at 11:06
  • Thanks Daniel that works....i have got some ImproperlyConfigured at /NewHandBook/validate/ AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance. Stack trace: http://dpaste.com/01TBQGR – vivek.p.n manu Mar 22 '19 at 11:24
  • Your configuration is not complete, see https://django-auth-ldap.readthedocs.io/en/latest/authentication.html#search-bind – Daniel Hepper Mar 22 '19 at 11:26
  • I have made the required changes but i get http://dpaste.com/2YST0GM..... – vivek.p.n manu Mar 22 '19 at 12:01
  • Try `return render('login/base.html', {'state': state, 'username': username})` instead of `return render_to_response(...)` – Daniel Hepper Mar 22 '19 at 13:52
  • Thanks Daniel....I know that I'm troubling you with all my exceptions each time. Its very hard time for me to finish this. With the progress, im getting some JSON response TemplateDoesNotExist at /NewHandBook/validate/ {'state': 'Inactive account', 'username': 'pvivek'}.....it says TemplateDoesNotExist although, i have provided proper location of base.html......StackTrace: http://dpaste.com/09JF2X5 – vivek.p.n manu Mar 22 '19 at 14:49
  • My mistake, it should be `return render(request, 'login/base.html', {'state': state, 'username': username})` – Daniel Hepper Mar 22 '19 at 14:52
  • I have updated the views.py.... just to make sure, LDAP authentication works fine. as per updated views.py, If username and password are proper, I'm redirecting to login/base.html and if not redirecting back to login.html again but it's redirecting to base.html each time although my username and password is proper. Could you please tell me how to know the response that is sent back from LDAP server and the details im sending to LDAP server. I think there is small gap but not sure where. – vivek.p.n manu Mar 22 '19 at 15:23
  • Hey Daniel.... Could you please help me here.. I don't understand what mistake I have done and I tried to find solution entire day but couldn't – vivek.p.n manu Mar 23 '19 at 17:14
0

Start using the default LoginView

def login(request):
    return LoginView.as_view(template_name='login.html')(request)

This shall work. If it does now implement your customized login method in a LoginView class...

stats con chris
  • 178
  • 1
  • 10