Skip to content
Snippets Groups Projects
Commit f970cf64 authored by Timothy Allen's avatar Timothy Allen
Browse files

Add the .basic_auth_required() decorator.

This is much less flexible than .login_required() (because HTTP
authentication is less flexible than custom login pages), but easier to
use in a simple proof-of-concept.
parent 81f261c6
Branches
No related tags found
No related merge requests found
...@@ -82,8 +82,14 @@ directives: ...@@ -82,8 +82,14 @@ directives:
Default: '(&(objectclass=Group)(userPrincipalName={}))' Default: '(&(objectclass=Group)(userPrincipalName={}))'
``LDAP_GROUP_MEMBERS_FIELD`` The field to return when searching for a group's members. ``LDAP_GROUP_MEMBERS_FIELD`` The field to return when searching for a group's members.
Default: 'member' Default: 'member'
``LDAP_LOGIN_VIEW`` The view to redirect to when a user needs to log-in. ``LDAP_LOGIN_VIEW`` Views decorated with :meth:`.login_required()` or
Default: 'login'. :meth:`.group_required()` will redirect
unauthenticated requests to this view. Default:
'login'.
``LDAP_REALM_NAME`` Views decorated with
:meth:`.basic_auth_required()` will use this as
the "realm" part of HTTP Basic Authentication when
responding to unauthenticated requests.
============================ =================================================== ============================ ===================================================
......
...@@ -5,7 +5,8 @@ from functools import wraps ...@@ -5,7 +5,8 @@ from functools import wraps
import re import re
import ldap import ldap
from flask import abort, current_app, g, redirect, url_for from flask import abort, current_app, g, redirect, url_for, request
from flask import make_response
try: try:
from flask import _app_ctx_stack as stack from flask import _app_ctx_stack as stack
...@@ -62,6 +63,7 @@ class LDAP(object): ...@@ -62,6 +63,7 @@ class LDAP(object):
'(&(objectclass=Group)(userPrincipalName={0}))') '(&(objectclass=Group)(userPrincipalName={0}))')
app.config.setdefault('LDAP_GROUP_MEMBERS_FIELD', 'member') app.config.setdefault('LDAP_GROUP_MEMBERS_FIELD', 'member')
app.config.setdefault('LDAP_LOGIN_VIEW', 'login') app.config.setdefault('LDAP_LOGIN_VIEW', 'login')
app.config.setdefault('LDAP_REALM_NAME', 'LDAP authentication')
if app.config['LDAP_USE_SSL'] or app.config['LDAP_USE_TLS']: if app.config['LDAP_USE_SSL'] or app.config['LDAP_USE_TLS']:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,
...@@ -266,3 +268,48 @@ class LDAP(object): ...@@ -266,3 +268,48 @@ class LDAP(object):
return func(*args, **kwargs) return func(*args, **kwargs)
return wrapped return wrapped
return wrapper return wrapper
def basic_auth_required(self, func):
"""When applied to a view function, any unauthenticated requests are
asked to authenticate via HTTP's standard Basic Authentication system.
Requests with credentials are checked with :meth:`.bind_user()`.
The user's browser will typically show them the contents of
LDAP_REALM_NAME as a prompt for which username and password to enter.
If the request's credentials are accepted by the LDAP server, the
username is stored in ``flask.g.ldap_username`` and the password in
``flask.g.ldap_password``.
:param func: The view function to decorate.
"""
def make_auth_required_response():
response = make_response("Authorization required", 401)
response.www_authenticate.set_basic(
current_app.config['LDAP_REALM_NAME'])
return response
@wraps(func)
def wrapped(*args, **kwargs):
if request.authorization is None:
req_username = None
req_password = None
else:
req_username = request.authorization.username
req_password = request.authorization.password
if req_username is None or req_password is None:
current_app.logger.debug("Got a request without auth data")
return make_auth_required_response()
if not self.bind_user(req_username, req_password):
current_app.logger.debug("User {0!r} gave wrong "
"password".format(req_username))
return make_auth_required_response()
g.ldap_username = req_username
g.ldap_password = req_password
return func(*args, **kwargs)
return wrapped
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment