Move ldap auth logic to function

This commit is contained in:
Amar Ramachandran
2017-06-29 10:32:13 -07:00
parent 300421792c
commit b9e08897ac
3 changed files with 41 additions and 29 deletions

View File

@@ -1,9 +1,8 @@
import logging
from flask import flash, redirect, render_template, request, url_for, Blueprint
from ldap3 import Server, Connection, ALL, NTLM, SIMPLE
from ldap3.core.exceptions import LDAPBindError, LDAPException
from flask_login import current_user, login_required, login_user, logout_user
from ldap3 import Server, Connection, SIMPLE
from redash import settings
from redash.authentication.google_oauth import create_and_login_user
@@ -28,25 +27,34 @@ def login(org_slug=None):
return redirect(next_path)
if request.method == 'POST':
try:
server = Server(settings.LDAP_HOST_URL)
conn = Connection(server, settings.LDAP_NAMESPACE+request.form['email'], password=request.form['password'], authentication=settings.LDAP_AUTHENTICATION_METHOD, auto_bind=True)
user = auth_ldap_user(request.form['email'], request.form['password'])
conn.search(settings.LDAP_BIND_DN, '(' + settings.LDAP_UID_KEY + '=' + request.form['email'] + ')', attributes=[settings.LDAP_DISPLAY_NAME_KEY, settings.LDAP_EMAIL_KEY])
if conn.entries[0] is not None:
user = create_and_login_user(current_org, conn.entries[0][settings.LDAP_DISPLAY_NAME_KEY].value, conn.entries[0][settings.LDAP_EMAIL_KEY].value)
return redirect(next_path or url_for('redash.index'))
else:
flash("Incorrect credentials.")
except LDAPBindError:
if user is not None:
create_and_login_user(current_org, user[settings.LDAP_DISPLAY_NAME_KEY][0], user[settings.LDAP_EMAIL_KEY][0])
return redirect(next_path or url_for('redash.index'))
else:
flash("Incorrect credentials.")
except LDAPException:
logging.exception("Unkown error connecting to LDAP.")
flash("Error connecting to LDAP.")
return render_template("login.html",
org_slug=org_slug,
next=next_path,
email=request.form.get('email', ''),
username_prompt=settings.LDAP_CUSTOM_USERNAME_PROMPT)
username_prompt=settings.LDAP_CUSTOM_USERNAME_PROMPT,
hide_forgot_password=True)
def auth_ldap_user(username, password):
server = Server(settings.LDAP_HOST_URL)
conn = Connection(server, settings.LDAP_BIND_DN, password=settings.LDAP_BIND_DN_PASSWORD, authentication=SIMPLE, 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

View File

@@ -125,21 +125,22 @@ REMOTE_USER_LOGIN_ENABLED = parse_boolean(os.environ.get("REDASH_REMOTE_USER_LOG
REMOTE_USER_HEADER = os.environ.get("REDASH_REMOTE_USER_HEADER", "X-Forwarded-Remote-User")
# If REDASH_PASSWORD_LOGIN_ENABLED is not false, then users will still be able to login through Redash instead of the LDAP server
LDAP_LOGIN_ENABLED = parse_boolean(os.environ.get("REDASH_LDAP_LOGIN_ENABLED", 'false'))
# Includes port (ex. 10.0.10.1:389)
LDAP_LOGIN_ENABLED = parse_boolean(os.environ.get('REDASH_LDAP_LOGIN_ENABLED', 'false'))
# The LDAP directory address (ex. ldap://10.0.10.1:389)
LDAP_HOST_URL = os.environ.get('REDASH_LDAP_URL', None)
# The DN of users who should be allowed to login (ex. cn=users,dc=organiztion,dc=local)
# The DN & password used to connect to LDAP to determine the identity of the user being authenticated. For AD this should be "org\\user".
LDAP_BIND_DN = os.environ.get('REDASH_LDAP_BIND_DN', None)
# NTSM for Active Directory
LDAP_AUTHENTICATION_METHOD = os.environ.get('REDASH_LDAP_AUTHENTICATION_METHOD', "SIMPLE")
# Namespace when logging in org\{username} ~needed for Active Directory
LDAP_NAMESPACE = os.environ.get('REDASH_LDAP_NAMESPACE', "")
LDAP_UID_KEY = os.environ.get('REDASH_LDAP_UID_KEY', "sAMAccountName")
LDAP_BIND_DN_PASSWORD = os.environ.get('REDASH_LDAP_BIND_DN_PASSWORD', '')
# AD/LDAP email and display name keys
LDAP_DISPLAY_NAME_KEY = os.environ.get('REDASH_LDAP_DISPLAY_NAME_KEY', "displayName")
LDAP_DISPLAY_NAME_KEY = os.environ.get('REDASH_LDAP_DISPLAY_NAME_KEY', 'displayName')
LDAP_EMAIL_KEY = os.environ.get('REDASH_LDAP_EMAIL_KEY', "mail")
# Prompt that should be shown above username/email field.
LDAP_CUSTOM_USERNAME_PROMPT = os.environ.get('REDASH_LDAP_LDAP_CUSTOM_USERNAME_PROMPT', "LDAP/AD/SSO username:")
LDAP_CUSTOM_USERNAME_PROMPT = os.environ.get('REDASH_LDAP_LDAP_CUSTOM_USERNAME_PROMPT', 'LDAP/AD/SSO username:')
# LDAP Search DN TEMPLATE (for AD this should be "(sAMAccountName=%(username)s)"")
LDAP_SEARCH_TEMPLATE = os.environ.get('REDASH_LDAP_SEARCH_TEMPLATE', '(cn=%(username)s)')
# The schema to bind to (ex. cn=users,dc=ORG,dc=local)
LDAP_SEARCH_DN = os.environ.get('REDASH_SEARCH_DN', None)
# Usually it will be a single path, but we allow to specify additional ones to override the default assets. Only the
# last one will be used for Flask templates.

View File

@@ -71,6 +71,9 @@
Log In
</button>
</form>
<hr>
<a href="{{ url_for("redash.forgot_password", org_slug=org_slug) }}">I forgot my password</a>
{% if not hide_forgot_password %}
<hr>
<a href="{{ url_for("redash.forgot_password", org_slug=org_slug) }}">I forgot my password</a>
{% endif %}
{% endblock %}