0001-backends-add-SAML-LDAP-authentication-backend-30125.patch
src/authentic2/backends/ldap_backend.py | ||
---|---|---|
316 | 316 |
'connect_with_user_credentials': True, |
317 | 317 |
# can reset password |
318 | 318 |
'can_reset_password': False, |
319 |
# entity id of the IDP based on the same LDAP |
|
320 |
'entity_id': '' |
|
319 | 321 |
} |
320 | 322 |
_REQUIRED = ('url', 'basedn') |
321 | 323 |
_TO_ITERABLE = ('url', 'groupsu', 'groupstaff', 'groupactive') |
... | ... | |
947 | 949 |
yield user_dn, user |
948 | 950 | |
949 | 951 |
@classmethod |
950 |
def get_users(cls):
|
|
952 |
def get_ldap_users(cls, blocks, user_filter=None):
|
|
951 | 953 |
logger = logging.getLogger(__name__) |
952 |
for block in cls.get_config():
|
|
954 |
for block in blocks:
|
|
953 | 955 |
conn = cls.get_connection(block) |
954 | 956 |
if conn is None: |
955 | 957 |
logger.warning(u'unable to synchronize with LDAP servers %r', block['url']) |
956 | 958 |
continue |
957 | 959 |
user_basedn = block.get('user_basedn') or block['basedn'] |
958 |
user_filter = block['sync_ldap_users_filter'] or block['user_filter'] |
|
960 |
user_filter = user_filter or block['sync_ldap_users_filter'] or block['user_filter']
|
|
959 | 961 |
user_filter = user_filter.replace('%s', '*') |
960 | 962 |
attrs = cls.get_ldap_attributes_names(block) |
961 |
users = cls.paged_search(conn, user_basedn, ldap.SCOPE_SUBTREE, user_filter,
|
|
963 |
return cls.paged_search(conn, user_basedn, ldap.SCOPE_SUBTREE, user_filter,
|
|
962 | 964 |
attrlist=attrs) |
963 |
backend = cls() |
|
964 |
for user_dn, data in users: |
|
965 |
# ignore referrals |
|
966 |
if not user_dn: |
|
967 |
continue |
|
968 |
data = cls.normalize_ldap_results(data) |
|
969 |
data['dn'] = user_dn |
|
970 |
yield backend._return_user(user_dn, None, conn, block, data) |
|
965 | ||
966 |
@classmethod |
|
967 |
def get_users(cls): |
|
968 |
blocks = cls.get_config() |
|
969 |
for user_dn, data in cls.get_ldap_users(blocks): |
|
970 |
# ignore referrals |
|
971 |
if not user_dn: |
|
972 |
continue |
|
973 |
data = cls.normalize_ldap_results(data) |
|
974 |
data['dn'] = user_dn |
|
975 |
yield backend._return_user(user_dn, None, conn, block, data) |
|
971 | 976 | |
972 | 977 |
@classmethod |
973 | 978 |
def ad_encoding(cls, s): |
src/authentic2_auth_saml/__init__.py | ||
---|---|---|
7 | 7 |
return ['mellon', __name__] |
8 | 8 | |
9 | 9 |
def get_authentication_backends(self): |
10 |
return ['authentic2_auth_saml.backends.SAMLBackend'] |
|
10 |
return ['authentic2_auth_saml.backends.SAMLLdapBackend', |
|
11 |
'authentic2_auth_saml.backends.SAMLBackend'] |
|
11 | 12 | |
12 | 13 |
def get_auth_frontends(self): |
13 | 14 |
return ['authentic2_auth_saml.auth_frontends.SAMLFrontend'] |
src/authentic2_auth_saml/app_ldap_saml_settings.py | ||
---|---|---|
1 | ||
2 |
class AppSettings(object): |
|
3 |
'''Thanks django-allauth''' |
|
4 |
__SENTINEL = object() |
|
5 | ||
6 |
def __init__(self, prefix): |
|
7 |
self.prefix = prefix |
|
8 | ||
9 |
def _setting(self, name, dflt=__SENTINEL): |
|
10 |
from django.conf import settings |
|
11 |
from django.core.exceptions import ImproperlyConfigured |
|
12 | ||
13 |
v = getattr(settings, self.prefix + name, dflt) |
|
14 |
if v is self.__SENTINEL: |
|
15 |
raise ImproperlyConfigured('Missing setting %r' % (self.prefix + name)) |
|
16 |
return v |
|
17 | ||
18 |
@property |
|
19 |
def enable(self): |
|
20 |
return self._setting('ENABLE', False) |
|
21 | ||
22 |
@property |
|
23 |
def enable_condition(self): |
|
24 |
return self._setting('ENABLE_CONDITION', None) |
|
25 | ||
26 | ||
27 |
import sys |
|
28 | ||
29 |
app_settings = AppSettings('A2_AUTH_SAML_LDAP') |
|
30 |
app_settings.__name__ = __name__ |
|
31 |
sys.modules[__name__] = app_settings |
src/authentic2_auth_saml/app_settings.py | ||
---|---|---|
19 | 19 |
def enable(self): |
20 | 20 |
return self._setting('ENABLE', False) |
21 | 21 | |
22 |
@property |
|
23 |
def ldap_enable(self): |
|
24 |
return self._setting('LDAP_ENABLE', False) |
|
25 | ||
22 | 26 | |
23 | 27 |
import sys |
24 | 28 |
src/authentic2_auth_saml/backends.py | ||
---|---|---|
1 |
import re |
|
2 | ||
3 |
from django.conf import settings |
|
4 | ||
1 | 5 |
from mellon.backends import SAMLBackend |
2 | 6 | |
3 | 7 |
from authentic2.middleware import StoreRequestMiddleware |
8 |
from authentic2.backends.ldap_backend import LDAPBackend |
|
4 | 9 | |
5 | 10 |
from . import app_settings |
6 | 11 | |
... | ... | |
22 | 27 | |
23 | 28 |
import lasso |
24 | 29 |
return lasso.SAML2_AUTHN_CONTEXT_PREVIOUS_SESSION |
30 | ||
31 | ||
32 |
class SAMLLdapBackend(SAMLBackend): |
|
33 | ||
34 |
def authenticate(self, saml_attributes, **credentials): |
|
35 |
if not app_settings.ldap_enable: |
|
36 |
return None |
|
37 |
if not getattr(settings, 'LDAP_AUTH_SETTINGS', []): |
|
38 |
return None |
|
39 |
no_ldap_for_entity_id = True |
|
40 |
for block in settings.LDAP_AUTH_SETTINGS: |
|
41 |
if block.get('entity_id', '') == saml_attributes['issuer']: |
|
42 |
no_ldap_for_entity_id = False |
|
43 |
break |
|
44 |
if no_ldap_for_entity_id: |
|
45 |
return None |
|
46 | ||
47 |
user_filter = block['sync_ldap_users_filter'] or block['user_filter'] |
|
48 | ||
49 |
args = [] |
|
50 |
# get user filter attribute names |
|
51 |
for group in re.findall('\w+=%\w+', user_filter): |
|
52 |
filter_name, filter_value = group.split('=') |
|
53 |
args.append(saml_attributes[filter_name][0]) |
|
54 |
user_filter = user_filter % tuple(args) |
|
55 | ||
56 |
users = LDAPBackend.get_ldap_users([block], user_filter) |
|
57 | ||
58 |
for user_dn, data in users: |
|
59 |
backend = LDAPBackend() |
|
60 |
data = backend.normalize_ldap_results(data) |
|
61 |
data['dn'] = user_dn |
|
62 |
conn = LDAPBackend.get_connection(block) |
|
63 |
return backend._return_user(user_dn, None, conn,block, data) |
|
64 |
else: |
|
65 |
return None |
|
25 |
- |