mirror of
https://github.com/getredash/redash.git
synced 2025-12-25 01:03:20 -05:00
Move ldap auth logic to function
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user