Skip to content
Snippets Groups Projects
Unverified Commit 94499517 authored by Alexandre Ferland's avatar Alexandre Ferland Committed by GitHub
Browse files

Merge branch 'master' into master

parents 2277533d c6f63c7f
No related branches found
No related tags found
No related merge requests found
language: python language: python
sudo: required sudo: required
dist: xenial dist: bionic
python: python:
- "3.5" - "3.5"
- "3.6" - "3.6"
- "3.7" - "3.7"
- "3.8"
- "3.9"
env: env:
- FLASK=1.1.1 - FLASK=1.1.2
- FLASK=1.0.4 - FLASK=1.0.4
- FLASK=0.12.4 - FLASK=0.12.5
install: install:
- pip install Flask==$FLASK - pip install Flask==$FLASK
- pip install -r dev_requirements.txt - pip install -r dev_requirements.txt
......
Flask-SimpleLDAP Flask-SimpleLDAP
================ ================
[![Build Status](https://travis-ci.org/admiralobvious/flask-simpleldap.svg?branch=master)](https://travis-ci.org/admiralobvious/flask-simpleldap) [![Build Status](https://travis-ci.com/alexferl/flask-simpleldap.svg?branch=master)](https://travis-ci.com/alexferl/flask-simpleldap)
Flask-SimpleLDAP provides LDAP authentication for Flask. Flask-SimpleLDAP provides LDAP authentication for Flask.
Flask-SimpleLDAP is compatible with and tested on Python 3.5, 3.6 and 3.7.
Quickstart Quickstart
---------- ----------
...@@ -13,40 +15,46 @@ First, install Flask-SimpleLDAP: ...@@ -13,40 +15,46 @@ First, install Flask-SimpleLDAP:
$ pip install flask-simpleldap $ pip install flask-simpleldap
Flask-SimpleLDAP depends, and will install for you, recent versions of Flask Flask-SimpleLDAP depends, and will install for you, recent versions of Flask
(0.12.4 or later) and [pyldap](https://github.com/pyldap/pyldap). Flask-SimpleLDAP is compatible (0.12.4 or later) and [python-ldap](https://python-ldap.org/).
with and tested on Python 3.5, 3.6 and 3.7. Please consult the [python-ldap installation instructions](https://www.python-ldap.org/en/latest/installing.html) if you get an error during installation.
Next, add a ``LDAP`` instance to your code and at least the three Next, add an ``LDAP`` instance to your code and at least the three
required configuration options: required configuration options. The complete sample from
[examples/basic_auth/app.py](examples/basic_auth/app.py) looks like this:
```python ```python
from flask import Flask from flask import Flask, g
from flask_simpleldap import LDAP from flask_simpleldap import LDAP
app = Flask(__name__) app = Flask(__name__)
#app.config['LDAP_HOST'] = 'ldap.example.org' # defaults to localhost
app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org' app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org'
app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org' app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org'
app.config['LDAP_PASSWORD'] = 'password' app.config['LDAP_PASSWORD'] = 'password'
ldap = LDAP(app) ldap = LDAP(app)
@app.route('/')
@app.route('/ldap') @ldap.basic_auth_required
@ldap.login_required def index():
def ldap_protected(): return 'Welcome, {0}!'.format(g.ldap_username)
return 'Success!'
if __name__ == '__main__': if __name__ == '__main__':
app.run() app.run()
``` ```
You can take a look at [examples/groups](examples/groups) for a more complete When the user visits the protected URL, the browser will prompt for the
example using LDAP groups. login and password via the built-in HTTP authentication window. Note that
with the default value of `LDAP_USER_OBJECT_FILTER` the login is expected
to match the [`userPrincipalName` attribute](https://ldapwiki.com/wiki/UserPrincipalName)
of the LDAP user, e.g. `me@mydomain.com`.
You can also take a look at [examples/blueprints](examples/blueprints) for an Once you get the basic example working, check out the more complex ones:
example using Flask's
* [examples/groups](examples/groups) demostrates using:
* `@ldap.login_required` for form/cookie-based auth, instead of basic HTTP authentication.
* `@ldap.group_required()` to restrict access to pages based on the user's LDAP groups.
* [examples/blueprints](examples/blueprints) implements the same functionality, but uses Flask's
[application factories](http://flask.pocoo.org/docs/patterns/appfactories/) [application factories](http://flask.pocoo.org/docs/patterns/appfactories/)
and [blueprints](http://flask.pocoo.org/docs/blueprints/). and [blueprints](http://flask.pocoo.org/docs/blueprints/).
...@@ -59,7 +67,7 @@ configuration, add the following at least LDAP_USER_OBJECT_FILTER and ...@@ -59,7 +67,7 @@ configuration, add the following at least LDAP_USER_OBJECT_FILTER and
LDAP_USER_OBJECT_FILTER. LDAP_USER_OBJECT_FILTER.
```python ```python
from flask import Flask from flask import Flask, g
from flask_simpleldap import LDAP from flask_simpleldap import LDAP
app = Flask(__name__) app = Flask(__name__)
...@@ -84,16 +92,13 @@ app.config['LDAP_GROUP_MEMBER_FILTER_FIELD'] = "cn" ...@@ -84,16 +92,13 @@ app.config['LDAP_GROUP_MEMBER_FILTER_FIELD'] = "cn"
ldap = LDAP(app) ldap = LDAP(app)
@app.route('/')
@app.route('/ldap') @ldap.basic_auth_required
@ldap.login_required def index():
def ldap_protected(): return 'Welcome, {0}!'.format(g.ldap_username)
return 'Success!'
if __name__ == '__main__': if __name__ == '__main__':
app.run() app.run()
``` ```
Resources Resources
......
from flask import Flask, g, request, session, redirect, url_for from flask import Flask, g
from flask_simpleldap import LDAP from flask_simpleldap import LDAP
app = Flask(__name__) app = Flask(__name__)
app.secret_key = 'dev key' #app.config['LDAP_HOST'] = 'ldap.example.org' # defaults to localhost
app.debug = True
app.config['LDAP_HOST'] = 'ldap.example.org'
app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org' app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org'
app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org' app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org'
app.config['LDAP_PASSWORD'] = 'password' app.config['LDAP_PASSWORD'] = 'password'
......
from flask import Flask, g, request, session, redirect, url_for from flask import Flask, g
from flask_simpleldap import LDAP from flask_simpleldap import LDAP
app = Flask(__name__) app = Flask(__name__)
app.secret_key = 'dev key'
app.debug = True
app.config['LDAP_OPENLDAP'] = True # Base
app.config['LDAP_OBJECTS_DN'] = 'dn'
app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication' app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication'
app.config['LDAP_HOST'] = 'openldap.example.org' app.config['LDAP_HOST'] = 'openldap.example.org'
app.config['LDAP_BASE_DN'] = 'dc=users,dc=openldap,dc=org' app.config['LDAP_BASE_DN'] = 'dc=users,dc=openldap,dc=org'
app.config['LDAP_USERNAME'] = 'cn=user,ou=servauth-users,dc=users,dc=openldap,dc=org' app.config['LDAP_USERNAME'] = 'cn=user,ou=servauth-users,dc=users,dc=openldap,dc=org'
app.config['LDAP_PASSWORD'] = 'password' app.config['LDAP_PASSWORD'] = 'password'
# OpenLDAP
app.config['LDAP_OPENLDAP'] = True
app.config['LDAP_OBJECTS_DN'] = 'dn'
app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=inetOrgPerson)(uid=%s))' app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=inetOrgPerson)(uid=%s))'
# Groups
app.config['LDAP_GROUP_MEMBERS_FIELD'] = "uniquemember"
app.config['LDAP_GROUP_OBJECT_FILTER'] = "(&(objectclass=groupOfUniqueNames)(cn=%s))"
app.config['LDAP_GROUP_MEMBER_FILTER'] = "(&(cn=*)(objectclass=groupOfUniqueNames)(uniquemember=%s))"
app.config['LDAP_GROUP_MEMBER_FILTER_FIELD'] = "cn"
ldap = LDAP(app) ldap = LDAP(app)
@app.route('/') @app.route('/')
......
...@@ -245,6 +245,7 @@ class LDAP(object): ...@@ -245,6 +245,7 @@ class LDAP(object):
current_app.config['LDAP_USER_GROUPS_FIELD']] current_app.config['LDAP_USER_GROUPS_FIELD']]
result = [re.findall(b'(?:cn=|CN=)(.*?),', group)[0] result = [re.findall(b'(?:cn=|CN=)(.*?),', group)[0]
for group in groups] for group in groups]
result = [r.decode('utf-8') for r in result]
return result return result
except ldap.LDAPError as e: except ldap.LDAPError as e:
raise LDAPException(self.error(e.args)) raise LDAPException(self.error(e.args))
...@@ -269,6 +270,7 @@ class LDAP(object): ...@@ -269,6 +270,7 @@ class LDAP(object):
records[0][1]: records[0][1]:
members = records[0][1][ members = records[0][1][
current_app.config['LDAP_GROUP_MEMBERS_FIELD']] current_app.config['LDAP_GROUP_MEMBERS_FIELD']]
members = [m.decode('utf-8') for m in members]
return members return members
except ldap.LDAPError as e: except ldap.LDAPError as e:
raise LDAPException(self.error(e.args)) raise LDAPException(self.error(e.args))
...@@ -297,8 +299,12 @@ class LDAP(object): ...@@ -297,8 +299,12 @@ class LDAP(object):
@wraps(func) @wraps(func)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
if g.user is None: if g.user is None:
next_path=request.full_path or request.path
if next_path == '/?':
return redirect(
url_for(current_app.config['LDAP_LOGIN_VIEW']))
return redirect(url_for(current_app.config['LDAP_LOGIN_VIEW'], return redirect(url_for(current_app.config['LDAP_LOGIN_VIEW'],
next=request.full_path or request.path)) next=next_path))
return func(*args, **kwargs) return func(*args, **kwargs)
return wrapped return wrapped
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment