Commit b2dc2618 authored by berumuron's avatar berumuron
Browse files

add: Provide LDAP authentication

parents 00fc16aa c598b998
......@@ -71,7 +71,13 @@ désactiver l'environnement avec (ne le faites toutefois pas immédiatement) :
reflets$ deactivate
```
Pour installer maintenant les sources du projet, exécutez :
Reflets permet de se connecter en LDAP et nécessite pour cela du module
[python-ldap](https://www.python-ldap.org). Ce module nécessite d’installer des
dépendances supplémentaires depuis votre gestionnaire de paquets. Vous pourrez
trouver la commande à exécuter [dans leur documentation
officielle](https://www.python-ldap.org/en/python-ldap-3.2.0/installing.html#build-prerequisites).
Pour installer maintenant les dépendances du projet, exécutez :
```console
reflets$ pip install -r requirements.txt
......
......@@ -5,6 +5,9 @@ itsdangerous==1.1.0
Jinja2==2.10.1
Markdown==3.1.1
MarkupSafe==1.1.1
pyasn1==0.4.6
pyasn1-modules==0.2.6
python-ldap==3.2.0
six==1.12.0
webencodings==0.5.1
Werkzeug==0.15.4
......@@ -27,3 +27,4 @@ install_requires =
Flask>=1.0.3
Markdown>=3.1.1
bleach>=3.1.0
python-ldap==3.2.0
......@@ -18,6 +18,10 @@ def create_app():
app.config.from_mapping(
SECRET_KEY=os.environ.get("REFLETS_SECRET_KEY", "a-dev-secret"),
DATABASE=os.environ.get("REFLETS_DATABASE", database_default_path),
LDAP_AUTH_SERVER=os.environ.get("REFLETS_LDAP_AUTH_SERVER", ""),
LDAP_DN=os.environ.get("REFLETS_LDAP_DN", ""),
LDAP_USERNAME=os.environ.get("REFLETS_LDAP_USERNAME", ""),
LDAP_PASSWORD=os.environ.get("REFLETS_LDAP_PASSWORD", ""),
)
try:
......
......@@ -11,6 +11,7 @@ from flask import (
g,
)
from .ldap_auth import Ldap, LdapException
from .models import User
......@@ -38,20 +39,44 @@ def load_logged_in_user():
@bp.route("/login", methods=("GET", "POST"))
def login():
ldap = Ldap()
ldap_error = False
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
user = User.find_by_username(username)
if user is not None and user.check_password(password):
logged_in = False
if not ldap.configured:
logged_in = user is not None and user.check_password(password)
else:
try:
logged_in = ldap.verify(username, password)
except LdapException as e:
ldap_error = str(e)
if logged_in and not user:
# Just create the user in DB so we can reference it by its
# username later. The password is set only to be sure that one
# cannot login with no password if ldap is deactivated.
user = User.create(username=username, password=password)
if logged_in:
session.clear()
session["user_id"] = user.id
flash("Vous êtes désormais connecté·e.", "success")
return redirect(url_for("index"))
elif ldap_error:
flash(
"Un problème est survenu lors de la connexion LDAP : {}.".format(
ldap_error
)
)
else:
flash("Les identifiants sont incorrects.")
return render_template("auth/login.html")
return render_template("auth/login.html", ldap_configured=ldap.configured)
@bp.route("/logout")
......
import ldap
from flask import current_app
class LdapException(RuntimeError):
def __init__(self, ldap_error):
message = ldap_error.args[0]
if "desc" in message:
message = message["desc"]
self.message = message
def __str__(self):
return self.message
class Ldap:
def __init__(self):
self.auth_server = current_app.config["LDAP_AUTH_SERVER"]
self.dn = current_app.config["LDAP_DN"]
self.username = current_app.config["LDAP_USERNAME"]
self.password = current_app.config["LDAP_PASSWORD"]
self.configured = self.auth_server != ""
def verify(self, username, password):
try:
connection = ldap.initialize(self.auth_server)
connection.simple_bind_s(self.username, self.password)
user = connection.search_s(
self.dn, ldap.SCOPE_SUBTREE, "(uid={})".format(username)
)
if not user:
return False
user_dn = user[0][0]
connection.bind_s(user_dn, password)
connection.unbind_s()
return True
except ldap.INVALID_CREDENTIALS:
return False
except ldap.LDAPError as e:
raise LdapException(e)
......@@ -2,7 +2,11 @@
{% block content %}
<div class="container container-small">
<h1>Connexion</h1>
{% if ldap_configured %}
<h1>Connexion (LDAP)</h1>
{% else %}
<h1>Connexion</h1>
{% endif %}
<form method="post">
{% include "alerts.html" %}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment