Hello,

I can’t get the LDAP Authentication working against an Active Directory LDAP.

I’m using the docker image redash/redash:8.0.0.b32245 with the following settings :

REDASH_LDAP_BIND_DN: MY_DOMAIN\\My_User
REDASH_LDAP_CUSTOM_USERNAME_PROMPT: 'Please enter domain account:'
REDASH_LDAP_DISPLAY_NAME_KEY: displayName
REDASH_LDAP_EMAIL_KEYvalue: mail
REDASH_LDAP_LOGIN_ENABLED: "true"
REDASH_LDAP_SEARCH_DN: dc=domain,dc=com
REDASH_LDAP_SEARCH_TEMPLATE: (sAMAccountName=%(username)s)
REDASH_LDAP_URL: ad_server.domain.com
REDASH_LDAP_USE_SSL: "false"
REDASH_PASSWORD_LOGIN_ENABLED: "false"

I first tried in SIMPLE mode but always got an error on the binding. I think that there is something wrong in the /app/redash/authentication/ldap_auth.py file :

def auth_ldap_user(username, password):
    server = Server(settings.LDAP_HOST_URL, use_ssl=settings.LDAP_SSL)
    if settings.LDAP_BIND_DN is not None:
        conn = Connection(
            server,
            settings.LDAP_BIND_DN,
            password=settings.LDAP_BIND_DN_PASSWORD,
            authentication=settings.LDAP_AUTH_METHOD,
            auto_bind=True
        )

It should be “user=settings.LDAP_BIND_DN,” instead of “settings.LDAP_BIND_DN”, right ?

After that change, it was still not working tho.

I switch to NTLM (from the ldap3 python documentation) and I tried directly in python :

from redash import settings
from ldap3 import Server, Connection

def auth_ldap_user(username, password):
    server = Server(settings.LDAP_HOST_URL, use_ssl=settings.LDAP_SSL)
    if settings.LDAP_BIND_DN is not None:
        conn = Connection(
            server,
            user=settings.LDAP_BIND_DN,
            password=settings.LDAP_BIND_DN_PASSWORD,
            authentication=settings.LDAP_AUTH_METHOD,
            auto_bind=True
        )
    else:
        conn = Connection(server, auto_bind=True)
	conn.search(settings.LDAP_SEARCH_DN, settings.LDAP_SEARCH_TEMPLATE % {"username": username}, attributes=[settings.LDAP_DISPLAY_NAME_KEY, settings.LDAP_EMAIL_KEY])
    if len(conn.entries) == 0:
		return None
    user = conn.entries[0]
    if not conn.rebind(user=user.entry_dn, password=password):
		return None
    return user

auth_ldap_user('myuser','mypassword')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in auth_ldap_user
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 326, in __init__
    self.do_auto_bind()
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 343, in do_auto_bind
    self.bind(read_server_info=True)
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 577, in bind
    raise LDAPUnknownAuthenticationMethodError(self.last_error)
ldap3.core.exceptions.LDAPUnknownAuthenticationMethodError: NTLM needs domain\username and a password

But if i replace the settings.LDAP_BIND_DN variable by its value, it’s working fine :

from redash import settings
from ldap3 import Server, Connection

print settings.LDAP_BIND_DN
MYDOMAIN\\My_User

def auth_ldap_user(username, password):
    server = Server(settings.LDAP_HOST_URL, use_ssl=settings.LDAP_SSL)
    if settings.LDAP_BIND_DN is not None:
        conn = Connection(
            server,
            user="MYDOMAIN\\My_User",
            password=settings.LDAP_BIND_DN_PASSWORD,
            authentication=settings.LDAP_AUTH_METHOD,
            auto_bind=True
        )
    else:
        conn = Connection(server, auto_bind=True)
	conn.search(settings.LDAP_SEARCH_DN, settings.LDAP_SEARCH_TEMPLATE % {"username": username}, attributes=[settings.LDAP_DISPLAY_NAME_KEY, settings.LDAP_EMAIL_KEY])
    if len(conn.entries) == 0:
		return None
    user = conn.entries[0]
    if not conn.rebind(user=user.entry_dn, password=password):
		return None
    return user

auth_ldap_user('myuser','mypassword')

Also try with SIMPLE mode and the result is the same, it’s not working with settings.LDAP_BIND_DN but working the value.

But it’s still not working on the website, still get a Internal Server Error :

[2019-11-26 09:56:37,170][PID:14][INFO][metrics] method=GET path=/ldap/login endpoint=ldap_auth_login status=200 content_type=text/html; charset=utf-8 content_length=1754 duration=1.89 query_count=0 query_duration=0.00

[2019-11-26 09:56:38,382] ERROR in app: Exception on /ldap/login [POST]

Traceback (most recent call last):

  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 271, in error_router
    return original_handler(e)
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/app/redash/authentication/ldap_auth.py", line 39, in login
    ldap_user = auth_ldap_user(request.form['email'], request.form['password'])
  File "/app/redash/authentication/ldap_auth.py", line 71, in auth_ldap_user
    auto_bind=True
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 326, in __init__
    self.do_auto_bind()
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 343, in do_auto_bind
    self.bind(read_server_info=True)
  File "/usr/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 577, in bind
    raise LDAPUnknownAuthenticationMethodError(self.last_error)
LDAPUnknownAuthenticationMethodError: NTLM needs domain\username and a password`

What am i doing wrong ? Is there someone who was successful to bind to an Active Directory ?

Regards,

Johan