Skip to content

Commit d7fb455

Browse files
authored
Merge pull request #98 from francoisfreitag/custom_session_clean
Add hook to clean attributes extracted from SAML response
2 parents 41b1e4c + 08c8d8e commit d7fb455

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Changes
33

44
UNRELEASED
55
----------
6+
- Added a clean_attributes hook allowing backends to restructure attributes extracted from SAML response.
67
- Log when fields are missing in a SAML response.
78
- Log when attribute_mapping maps to nonexistent User fields.
89
- Dropped compatibility for Python < 2.7 and Django < 1.8.

djangosaml2/backends.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def authenticate(self, request, session_info=None, attribute_mapping=None,
7171
logger.error('"ava" key not found in session_info')
7272
return None
7373

74-
attributes = session_info['ava']
74+
attributes = self.clean_attributes(session_info['ava'])
7575
if not attributes:
7676
logger.error('The attributes dictionary is empty')
7777

@@ -120,6 +120,10 @@ def is_authorized(self, attributes, attribute_mapping):
120120
"""
121121
return True
122122

123+
def clean_attributes(self, attributes):
124+
"""Hook to clean attributes from the SAML response."""
125+
return attributes
126+
123127
def clean_user_main_attribute(self, main_attribute):
124128
"""Performs any cleaning on the user main attribute (which
125129
usually is "username") prior to using it to get or

tests/testprofiles/tests.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,33 @@ def test_django_user_main_attribute_lookup(self):
166166
self.assertEqual(
167167
backend.get_django_user_main_attribute_lookup(),
168168
'__iexact')
169+
170+
171+
class LowerCaseSaml2Backend(Saml2Backend):
172+
def clean_attributes(self, attributes):
173+
return dict([k.lower(), v] for k, v in attributes.items())
174+
175+
176+
class LowerCaseSaml2BackendTest(TestCase):
177+
def test_update_user_clean_attributes(self):
178+
user = User.objects.create(username='john')
179+
attribute_mapping = {
180+
'uid': ('username', ),
181+
'mail': ('email', ),
182+
'cn': ('first_name', ),
183+
'sn': ('last_name', ),
184+
}
185+
attributes = {
186+
'UID': ['john'],
187+
'MAIL': ['john@example.com'],
188+
'CN': ['John'],
189+
'SN': [],
190+
}
191+
192+
backend = LowerCaseSaml2Backend()
193+
user = backend.authenticate(
194+
None,
195+
session_info={'ava': attributes},
196+
attribute_mapping=attribute_mapping,
197+
)
198+
self.assertIsNotNone(user)

0 commit comments

Comments
 (0)