Mfreeman
Mfreeman

Reputation: 3958

Django 2.1.3 LDAP authentication not authenticating to backend

I am trying to create a django(v2.1.3) web app with a simple LDAP authentication. The code runs and i don't exactly know why it isn't working. It doesn't seem to be authenticating the user info to the LDAP backend i have connected to. When i fill out the form it will always return with "inactive user", when i know the user is on the test server. All i want is to just have it recognize that it is a "valid user"

I'm running it against a LDAP test server found here http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/

here are the changes i've made in the project:

settings.py

import ldap
from django_auth_ldap.config import LDAPSearch


AUTH_LDAP_SERVER_URI = "ldap://ldap.forumsys.com:389"
AUTH_LDAP_CONNECTION_OPTIONS = {
    ldap.OPT_REFERRALS: 0
}

AUTH_LDAP_BIND_DN = "cn=read-only-admin,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD = "password"
AUTH_LDAP_USER_SEARCH = LDAPSearch(
    "dc=example,dc=com",
    ldap.SCOPE_SUBTREE, "(uid=%(user)s)")

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

AUTHENTICATION_BACKENDS = [
    'django_auth_ldap.backend.LDAPBackend',
]

views.py

from django.contrib.auth import authenticate, login
from django.shortcuts import render    

def login_user(request):

    email = password = ""
    state = ""

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

        print (email, password)

        user = authenticate(username=request.POST.get('email'), password=request.POST.get('password'))
        if user is not None:
            login(request, user)
            state = "Valid account"
        else:
            state = "Inactive account"

    return render(request, 'KPI/auth.html', {'state': state, 'email': email})

auth.html

<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        {{state}}
        <form action="" method="post"> {% csrf_token %}
            Email address: <input type="text" name="email" value="{{ email }}" />
            Password: <input type="password" name="password" value="" />
            <input type="submit" value="Log in" />
        </form>
    </body>
</html>

EDIT:

i know the settings configuration is correct because when i run ldapsearch -W -h ldap.forumsys.com -p 389 -D "cn=read-only-admin,dc=example,dc=com" -b "dc=example,dc=com" -s sub "uid=boyle" it will return with just the 'boyle' info

EDIT 2:

I used a logger to get this error when a user comes back as none

Caught LDAPError while authenticating tesla: CONNECT_ERROR({'desc': 'Connect error', 'info': 'error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (self signed certificate in certificate chain)'},)

Upvotes: 2

Views: 4497

Answers (1)

Steven Graham
Steven Graham

Reputation: 1300

It looks like you aren't using the right hostname for the server.

ldap://ldap.forumsys:389 should be: ldap://ldap.forumsys.com:389

Using an ldap search tool such as ldapsearch can help verify if the server is responding correctly:

$ ldapsearch -LLL -h ldap.forumsys -p 389 -D 'cn=read-only-admin,dc=example,dc=com' 
-w password -b 'ou=mathematicians,dc=example,dc=com' -s sub "(objectclass=*)"
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

$ ldapsearch -LLL -h ldap.forumsys.com -p 389 -D 'cn=read-only- 
admin,dc=example,dc=com' -w password -b 'ou=mathematicians,dc=example,dc=com' 
-s sub "(objectclass=*)"
dn: ou=mathematicians,dc=example,dc=com
uniqueMember: uid=euclid,dc=example,dc=com
uniqueMember: uid=riemann,dc=example,dc=com
uniqueMember: uid=euler,dc=example,dc=com
uniqueMember: uid=gauss,dc=example,dc=com
uniqueMember: uid=test,dc=example,dc=com
ou: mathematicians
cn: Mathematicians
objectClass: groupOfUniqueNames
objectClass: top

If you get data back that means it is finding the user. The result: 0 Success just means that the ldap server was able to successfully search the tree.

It looks like the Django module has two methods of authenticating a user. The setup you have configured first attempts to lookup the record (via uid) and then uses the found DN to then bind (again) with the password supplied. As an example it will search (uid=boyle), then find the DN: uid=boyle,dc=example,dc=com. Then it will bind to the LDAP server with DN: uid=boyle,dc=example,dc=com, password supplied via login page.

In reponse to Edit 2 above:

The following error means that the library is trying to negotiate a TLS connection:

Caught LDAPError while authenticating tesla: CONNECT_ERROR({'desc': 
'Connect error', 'info': 'error:14090086:SSL 
routines:ssl3_get_server_certificate:certificate verify failed (self 
signed certificate in certificate chain)'},)

If you are connecting to ldap on port 389 (ldap://) then TLS shouldn't be negotiated and can be disabled by setting:

AUTH_LDAP_START_TLS = False

In settings.py.

For security reasons its a good idea to use ldaps, and configure TLS options via the AUTH_LDAP_CONNECTION_OPTIONS dictionary.

Upvotes: 3

Related Questions