diff --git a/mellon/views.py b/mellon/views.py
index 9ebf645..899989f 100644
--- a/mellon/views.py
+++ b/mellon/views.py
@@ -209,16 +209,24 @@ class LoginView(ProfileMixin, LogMixin, View):
'error_redirect_after_timeout': error_redirect_after_timeout,
})
+ def get_attribute_value(self, attribute, attribute_value):
+ # check attribute_value contains only text
+ for node in attribute_value.any:
+ if not isinstance(node, lasso.MiscTextNode) or not node.textChild:
+ self.log.warning('unsupported attribute %s', attribute.exportToXml())
+ return None
+ return ''.join(lasso_decode(node.content) for node in attribute_value.any)
+
def sso_success(self, request, login):
attributes = {}
attribute_statements = login.assertion.attributeStatement
for ats in attribute_statements:
for at in ats.attribute:
values = attributes.setdefault(at.name, [])
- for value in at.attributeValue:
- contents = [lasso_decode(any.exportToXml()) for any in value.any]
- content = ''.join(contents)
- values.append(content)
+ for attribute_value in at.attributeValue:
+ content = self.get_attribute_value(at, attribute_value)
+ if content is not None:
+ values.append(content)
attributes['issuer'] = login.remoteProviderId
if login.nameIdentifier:
name_id = login.nameIdentifier
diff --git a/tests/test_sso_slo.py b/tests/test_sso_slo.py
index 83a50cc..97285d3 100644
--- a/tests/test_sso_slo.py
+++ b/tests/test_sso_slo.py
@@ -32,6 +32,7 @@ from django.utils.six.moves.urllib import parse as urlparse
from django.utils.encoding import force_str
from mellon.utils import create_metadata
+from mellon.views import lasso_decode
from httmock import all_requests, HTTMock, response as mock_response
@@ -121,6 +122,7 @@ class MockIdp(object):
break
else:
attribute = lasso.Saml2Attribute()
+ attribute.name = name
attributes.append(attribute)
statement.attribute = attributes
attribute_values = list(attribute.attributeValue)
@@ -138,6 +140,7 @@ class MockIdp(object):
atv.any = value_any
add_attribute('email', 'john', '.doe@gmail.com')
add_attribute('wtf', 'john', lasso.MiscTextNode.newWithXmlNode('coucou'))
+ add_attribute('first_name', 'Fr\xe9d\xe9ric')
if not auth_result and msg:
login.response.status.statusMessage = msg
@@ -164,8 +167,8 @@ class MockIdp(object):
del self.artifact
del self.artifact_message
login.buildResponseMsg()
- assert 'rsa-sha256' in login.msgBody
- return '\n' + login.msgBody
+ assert 'rsa-sha256' in lasso_decode(login.msgBody)
+ return '\n' + lasso_decode(login.msgBody)
def mock_artifact_resolver(self):
@all_requests
@@ -204,6 +207,9 @@ def test_sso(db, app, idp, caplog, sp_settings):
assert 'created new user' in caplog.text
assert 'logged in using SAML' in caplog.text
assert urlparse.urlparse(response['Location']).path == sp_settings.LOGIN_REDIRECT_URL
+ assert app.session['mellon_session']['first_name'] == ['Fr\xe9d\xe9ric']
+ assert app.session['mellon_session']['email'] == ['john.doe@gmail.com']
+ assert app.session['mellon_session']['wtf'] == []
def test_sso_request_denied(db, app, idp, caplog, sp_settings):