Skip to content

Commit

Permalink
Merge pull request #50 from mwielgoszewski/ldap-login
Browse files Browse the repository at this point in the history
Add ldap as an authentication method
  • Loading branch information
mwielgoszewski committed May 28, 2016
2 parents 49d89ec + e9c3d8b commit 01aabd4
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 8 deletions.
10 changes: 8 additions & 2 deletions doorman/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from doorman.assets import assets
from doorman.manage import blueprint as backend
from doorman.extensions import (
db, debug_toolbar, log_tee, login_manager, mail, make_celery, metrics,
migrate, rule_manager
db, debug_toolbar, ldap_manager, log_tee, login_manager, mail,
make_celery, metrics, migrate, rule_manager
)
from doorman.settings import ProdConfig
from doorman.tasks import celery
Expand Down Expand Up @@ -105,6 +105,12 @@ def register_auth_method(app):
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'warning'

if app.config['DOORMAN_AUTH_METHOD'] == 'ldap':
ldap_manager.init_app(app)
return

# no other authentication methods left, falling back to OAuth

if app.config['DOORMAN_AUTH_METHOD'] != 'doorman':
login_manager.login_message = None
login_manager.needs_refresh_message = None
Expand Down
2 changes: 2 additions & 0 deletions doorman/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from celery import Celery
from flask_bcrypt import Bcrypt
from flask_debugtoolbar import DebugToolbarExtension
from flask_ldap3_login import LDAP3LoginManager
from flask_login import LoginManager
from flask_mail import Mail
from flask_migrate import Migrate
Expand Down Expand Up @@ -229,6 +230,7 @@ def init_app(self, app):
migrate = Migrate()
debug_toolbar = DebugToolbarExtension()
log_tee = LogTee()
ldap_manager = LDAP3LoginManager()
login_manager = LoginManager()
metrics = Metrics()
rule_manager = RuleManager()
29 changes: 28 additions & 1 deletion doorman/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,12 @@ class Config(object):
# only applicable when DOORMAN_AUTH_METHOD = 'doorman'
SESSION_PROTECTION = "strong"

BCRYPT_LOG_ROUNDS = 13

DOORMAN_AUTH_METHOD = None
# DOORMAN_AUTH_METHOD = 'doorman'
# DOORMAN_AUTH_METHOD = 'google'
# DOORMAN_AUTH_METHOD = 'ldap'

DOORMAN_OAUTH_GOOGLE_ALLOWED_DOMAINS = [
]
Expand All @@ -131,7 +134,31 @@ class Config(object):
DOORMAN_OAUTH_CLIENT_ID = ''
DOORMAN_OAUTH_CLIENT_SECRET = ''

BCRYPT_LOG_ROUNDS = 13
# When using DOORMAN_AUTH_METHOD = 'ldap', see
# http://flask-ldap3-login.readthedocs.io/en/latest/configuration.html#core
# Note: not all configuration options are documented at the link
# provided above. A complete list of options can be groked by
# reviewing the the flask-ldap3-login code.

# LDAP_HOST = None
# LDAP_PORT = 636
# LDAP_USE_SSL = True
# LDAP_BASE_DN = 'dc=example,dc=org'
# LDAP_USER_DN = 'ou=People'
# LDAP_GROUP_DN = ''
# LDAP_USER_OBJECT_FILTER = '(objectClass=inetOrgPerson)'
# LDAP_USER_LOGIN_ATTR = 'uid'
# LDAP_USER_RDN_ATTR = 'uid'
# LDAP_GROUP_SEARCH_SCOPE = 'SEARCH_SCOPE_WHOLE_SUBTREE'
# LDAP_GROUP_OBJECT_FILTER = '(cn=*)(objectClass=groupOfUniqueNames)'
# LDAP_GROUP_MEMBERS_ATTR = 'uniquemember'
# LDAP_GET_GROUP_ATTRIBUTES = ['cn']
# LDAP_OPT_X_TLS_CACERTFILE = None
# LDAP_OPT_X_TLS_CERTIFICATE_FILE = None
# LDAP_OPT_X_TLS_PRIVATE_KEY_FILE = None
# LDAP_OPT_X_TLS_REQUIRE_CERT = 2 # ssl.CERT_REQUIRED
# LDAP_OPT_X_TLS_USE_VERSION = 3 # ssl.PROTOCOL_TLSv1
# LDAP_OPT_X_TLS_VALID_NAMES = []


class ProdConfig(Config):
Expand Down
2 changes: 1 addition & 1 deletion doorman/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</div>
</div>

{% if form.auth_method == 'doorman' %}
{% if form.auth_method in ('doorman', 'ldap') %}

<div class="form-group">
<div class="col-sm-10">
Expand Down
27 changes: 24 additions & 3 deletions doorman/users/forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-

from flask import current_app
from flask_ldap3_login import AuthenticationResponseStatus

from flask_wtf import Form
from wtforms import BooleanField, PasswordField, StringField
from wtforms.validators import DataRequired, Optional

from doorman.extensions import bcrypt
from doorman.extensions import bcrypt, ldap_manager
from doorman.models import User


Expand Down Expand Up @@ -42,10 +43,30 @@ def validate(self):
self.username.errors.append(error_message)
return False

return True

elif current_app.config['DOORMAN_AUTH_METHOD'] == 'ldap':
pass
result = ldap_manager.authenticate(
self.username.data,
self.password.data
)

if result.status == AuthenticationResponseStatus.fail:
self.username.errors.append(error_message)
return False

self.user = ldap_manager._save_user(
result.user_dn,
result.user_id,
result.user_info,
result.user_groups
)
return True

elif current_app.config['DOORMAN_AUTH_METHOD'] is None:
return True

return True
return False

@property
def auth_method(self):
Expand Down
17 changes: 16 additions & 1 deletion doorman/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from oauthlib.oauth2 import OAuth2Error

from .forms import LoginForm
from doorman.extensions import login_manager
from doorman.extensions import ldap_manager, login_manager
from doorman.models import User
from doorman.utils import flash_errors

Expand All @@ -29,6 +29,21 @@ def load_user(user_id):
return User.get_by_id(int(user_id))


@ldap_manager.save_user
def save_user(dn, username, userdata, memberships):
user = User.query.filter_by(username=username).first()
kwargs = {}
kwargs['username'] = username

if 'givenName' in userdata:
kwargs['first_name'] = userdata['givenName'][0]

if 'sn' in userdata:
kwargs['last_name'] = userdata['sn'][0]

return user.update(**kwargs) if user else User.create(**kwargs)


@blueprint.route('/login', methods=['GET', 'POST'])
def login():
next = request.args.get('next', url_for('manage.index'))
Expand Down
4 changes: 4 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ blinker==1.4
celery==3.1.23
cffi==1.6.0
cssmin==0.2.0
enum34==1.1.6
factory-boy==2.7.0
fake-factory==0.5.7
Flask==0.10.1
Flask-Assets==0.11
Flask-Bcrypt==0.7.1
Flask-DebugToolbar==0.10.0
flask-ldap3-login==0.9.9
Flask-Login==0.3.2
Flask-Mail==0.9.1
Flask-Migrate==1.8.0
Expand All @@ -27,13 +29,15 @@ itsdangerous==0.24
Jinja2==2.8
jsmin==2.2.1
kombu==3.0.35
ldap3==1.3.1
Mako==1.0.4
MarkupSafe==0.23
mock==2.0.0
oauthlib==1.1.1
pbr==1.9.1
psycopg2==2.6.1
py==1.4.31
pyasn1==0.1.9
pycparser==2.14
pytest==2.9.1
python-dateutil==2.5.3
Expand Down
4 changes: 4 additions & 0 deletions requirements/prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ blinker==1.4
celery==3.1.23
cffi==1.6.0
cssmin==0.2.0
enum34==1.1.6
Flask==0.10.1
Flask-Assets==0.11
Flask-Bcrypt==0.7.1
Flask-DebugToolbar==0.10.0
flask-ldap3-login==0.9.9
Flask-Login==0.3.2
Flask-Mail==0.9.1
Flask-Migrate==1.8.0
Expand All @@ -22,10 +24,12 @@ itsdangerous==0.24
Jinja2==2.8
jsmin==2.2.1
kombu==3.0.35
ldap3==1.3.1
Mako==1.0.4
MarkupSafe==0.23
oauthlib==1.1.1
psycopg2==2.6.1
pyasn1==0.1.9
pycparser==2.14
python-editor==1.0
pytz==2016.4
Expand Down
11 changes: 11 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,36 @@
'alembic==0.8.6',
'amqp==1.4.9',
'anyjson==0.3.3',
'bcrypt==2.0.0',
'billiard==3.3.0.23',
'blinker==1.4',
'celery==3.1.23',
'cffi==1.6.0',
'cssmin==0.2.0',
'enum34==1.1.6',
'Flask==0.10.1',
'Flask-Assets==0.11',
'Flask-Bcrypt==0.7.1',
'Flask-DebugToolbar==0.10.0',
'flask-ldap3-login==0.9.9',
'Flask-Login==0.3.2',
'Flask-Mail==0.9.1',
'Flask-Migrate==1.8.0',
'flask-paginate==0.4.1',
'Flask-Script==2.0.5',
'Flask-SQLAlchemy==2.1',
'Flask-WTF==0.12',
'itsdangerous==0.24',
'Jinja2==2.8',
'jsmin==2.2.1',
'kombu==3.0.35',
'ldap3==1.3.1',
'Mako==1.0.4',
'MarkupSafe==0.23',
'oauthlib==1.1.1',
'psycopg2==2.6.1',
'pyasn1==0.1.9',
'pycparser==2.14',
'python-editor==1.0',
'pytz==2016.4',
'redis==2.10.5',
Expand Down

0 comments on commit 01aabd4

Please sign in to comment.