Skip to content

Commit 9449951

Browse files
authored
Merge branch 'master' into master
2 parents 2277533 + c6f63c7 commit 9449951

File tree

5 files changed

+56
-39
lines changed

5 files changed

+56
-39
lines changed

.travis.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
language: python
22
sudo: required
3-
dist: xenial
3+
dist: bionic
44
python:
55
- "3.5"
66
- "3.6"
77
- "3.7"
8+
- "3.8"
9+
- "3.9"
810
env:
9-
- FLASK=1.1.1
11+
- FLASK=1.1.2
1012
- FLASK=1.0.4
11-
- FLASK=0.12.4
13+
- FLASK=0.12.5
1214
install:
1315
- pip install Flask==$FLASK
1416
- pip install -r dev_requirements.txt

README.md

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
Flask-SimpleLDAP
22
================
33

4-
[![Build Status](https://travis-ci.org/admiralobvious/flask-simpleldap.svg?branch=master)](https://travis-ci.org/admiralobvious/flask-simpleldap)
4+
[![Build Status](https://travis-ci.com/alexferl/flask-simpleldap.svg?branch=master)](https://travis-ci.com/alexferl/flask-simpleldap)
55

66
Flask-SimpleLDAP provides LDAP authentication for Flask.
77

8+
Flask-SimpleLDAP is compatible with and tested on Python 3.5, 3.6 and 3.7.
9+
810
Quickstart
911
----------
1012

@@ -13,40 +15,46 @@ First, install Flask-SimpleLDAP:
1315
$ pip install flask-simpleldap
1416

1517
Flask-SimpleLDAP depends, and will install for you, recent versions of Flask
16-
(0.12.4 or later) and [pyldap](https://github.com/pyldap/pyldap). Flask-SimpleLDAP is compatible
17-
with and tested on Python 3.5, 3.6 and 3.7.
18+
(0.12.4 or later) and [python-ldap](https://python-ldap.org/).
19+
Please consult the [python-ldap installation instructions](https://www.python-ldap.org/en/latest/installing.html) if you get an error during installation.
1820

19-
Next, add a ``LDAP`` instance to your code and at least the three
20-
required configuration options:
21+
Next, add an ``LDAP`` instance to your code and at least the three
22+
required configuration options. The complete sample from
23+
[examples/basic_auth/app.py](examples/basic_auth/app.py) looks like this:
2124

2225
```python
23-
from flask import Flask
26+
from flask import Flask, g
2427
from flask_simpleldap import LDAP
2528

2629
app = Flask(__name__)
30+
#app.config['LDAP_HOST'] = 'ldap.example.org' # defaults to localhost
2731
app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org'
2832
app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org'
2933
app.config['LDAP_PASSWORD'] = 'password'
3034

3135
ldap = LDAP(app)
3236

33-
34-
@app.route('/ldap')
35-
@ldap.login_required
36-
def ldap_protected():
37-
return 'Success!'
38-
37+
@app.route('/')
38+
@ldap.basic_auth_required
39+
def index():
40+
return 'Welcome, {0}!'.format(g.ldap_username)
3941

4042
if __name__ == '__main__':
4143
app.run()
42-
4344
```
4445

45-
You can take a look at [examples/groups](examples/groups) for a more complete
46-
example using LDAP groups.
46+
When the user visits the protected URL, the browser will prompt for the
47+
login and password via the built-in HTTP authentication window. Note that
48+
with the default value of `LDAP_USER_OBJECT_FILTER` the login is expected
49+
to match the [`userPrincipalName` attribute](https://ldapwiki.com/wiki/UserPrincipalName)
50+
of the LDAP user, e.g. `[email protected]`.
4751

48-
You can also take a look at [examples/blueprints](examples/blueprints) for an
49-
example using Flask's
52+
Once you get the basic example working, check out the more complex ones:
53+
54+
* [examples/groups](examples/groups) demostrates using:
55+
* `@ldap.login_required` for form/cookie-based auth, instead of basic HTTP authentication.
56+
* `@ldap.group_required()` to restrict access to pages based on the user's LDAP groups.
57+
* [examples/blueprints](examples/blueprints) implements the same functionality, but uses Flask's
5058
[application factories](http://flask.pocoo.org/docs/patterns/appfactories/)
5159
and [blueprints](http://flask.pocoo.org/docs/blueprints/).
5260

@@ -59,7 +67,7 @@ configuration, add the following at least LDAP_USER_OBJECT_FILTER and
5967
LDAP_USER_OBJECT_FILTER.
6068

6169
```python
62-
from flask import Flask
70+
from flask import Flask, g
6371
from flask_simpleldap import LDAP
6472

6573
app = Flask(__name__)
@@ -84,16 +92,13 @@ app.config['LDAP_GROUP_MEMBER_FILTER_FIELD'] = "cn"
8492

8593
ldap = LDAP(app)
8694

87-
88-
@app.route('/ldap')
89-
@ldap.login_required
90-
def ldap_protected():
91-
return 'Success!'
92-
95+
@app.route('/')
96+
@ldap.basic_auth_required
97+
def index():
98+
return 'Welcome, {0}!'.format(g.ldap_username)
9399

94100
if __name__ == '__main__':
95101
app.run()
96-
97102
```
98103

99104
Resources

examples/basic_auth/app.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
from flask import Flask, g, request, session, redirect, url_for
1+
from flask import Flask, g
22
from flask_simpleldap import LDAP
33

44
app = Flask(__name__)
5-
app.secret_key = 'dev key'
6-
app.debug = True
7-
8-
app.config['LDAP_HOST'] = 'ldap.example.org'
5+
#app.config['LDAP_HOST'] = 'ldap.example.org' # defaults to localhost
96
app.config['LDAP_BASE_DN'] = 'OU=users,dc=example,dc=org'
107
app.config['LDAP_USERNAME'] = 'CN=user,OU=Users,DC=example,DC=org'
118
app.config['LDAP_PASSWORD'] = 'password'

examples/basic_auth/app_oldap.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
1-
from flask import Flask, g, request, session, redirect, url_for
1+
from flask import Flask, g
22
from flask_simpleldap import LDAP
33

44
app = Flask(__name__)
5-
app.secret_key = 'dev key'
6-
app.debug = True
75

8-
app.config['LDAP_OPENLDAP'] = True
9-
app.config['LDAP_OBJECTS_DN'] = 'dn'
6+
# Base
107
app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication'
118
app.config['LDAP_HOST'] = 'openldap.example.org'
129
app.config['LDAP_BASE_DN'] = 'dc=users,dc=openldap,dc=org'
1310
app.config['LDAP_USERNAME'] = 'cn=user,ou=servauth-users,dc=users,dc=openldap,dc=org'
1411
app.config['LDAP_PASSWORD'] = 'password'
12+
13+
# OpenLDAP
14+
app.config['LDAP_OPENLDAP'] = True
15+
app.config['LDAP_OBJECTS_DN'] = 'dn'
1516
app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=inetOrgPerson)(uid=%s))'
1617

18+
# Groups
19+
app.config['LDAP_GROUP_MEMBERS_FIELD'] = "uniquemember"
20+
app.config['LDAP_GROUP_OBJECT_FILTER'] = "(&(objectclass=groupOfUniqueNames)(cn=%s))"
21+
app.config['LDAP_GROUP_MEMBER_FILTER'] = "(&(cn=*)(objectclass=groupOfUniqueNames)(uniquemember=%s))"
22+
app.config['LDAP_GROUP_MEMBER_FILTER_FIELD'] = "cn"
23+
1724
ldap = LDAP(app)
1825

1926
@app.route('/')

flask_simpleldap/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ def get_user_groups(self, user):
245245
current_app.config['LDAP_USER_GROUPS_FIELD']]
246246
result = [re.findall(b'(?:cn=|CN=)(.*?),', group)[0]
247247
for group in groups]
248+
result = [r.decode('utf-8') for r in result]
248249
return result
249250
except ldap.LDAPError as e:
250251
raise LDAPException(self.error(e.args))
@@ -269,6 +270,7 @@ def get_group_members(self, group):
269270
records[0][1]:
270271
members = records[0][1][
271272
current_app.config['LDAP_GROUP_MEMBERS_FIELD']]
273+
members = [m.decode('utf-8') for m in members]
272274
return members
273275
except ldap.LDAPError as e:
274276
raise LDAPException(self.error(e.args))
@@ -297,8 +299,12 @@ def login_required(func):
297299
@wraps(func)
298300
def wrapped(*args, **kwargs):
299301
if g.user is None:
302+
next_path=request.full_path or request.path
303+
if next_path == '/?':
304+
return redirect(
305+
url_for(current_app.config['LDAP_LOGIN_VIEW']))
300306
return redirect(url_for(current_app.config['LDAP_LOGIN_VIEW'],
301-
next=request.full_path or request.path))
307+
next=next_path))
302308
return func(*args, **kwargs)
303309

304310
return wrapped

0 commit comments

Comments
 (0)