allow federating transient NameID using an attribute (fixes #10619)
This commit is contained in:
parent
f70986795d
commit
49a5254363
8
README
8
README
|
@ -247,6 +247,14 @@ MELLON_VERIFY_SSL_CERTIFICATE
|
||||||
Verify SSL certificate when doing HTTP requests, used when resolving artifacts.
|
Verify SSL certificate when doing HTTP requests, used when resolving artifacts.
|
||||||
Default is True.
|
Default is True.
|
||||||
|
|
||||||
|
MELLON_TRANSIENT_FEDERATION_ATTRIBUTE
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Name of an attribute to use in replacement of the NameID content when the NameID
|
||||||
|
format is transient. Without it no login using a transient NameID can occur with
|
||||||
|
the default adapter.
|
||||||
|
Default is None.
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,22 @@ class DefaultAdapter(object):
|
||||||
|
|
||||||
def lookup_user(self, idp, saml_attributes):
|
def lookup_user(self, idp, saml_attributes):
|
||||||
User = auth.get_user_model()
|
User = auth.get_user_model()
|
||||||
name_id = saml_attributes['name_id_content']
|
transient_federation_attribute = utils.get_setting(idp, 'TRANSIENT_FEDERATION_ATTRIBUTE')
|
||||||
|
if saml_attributes['name_id_format'] == lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT:
|
||||||
|
if (transient_federation_attribute
|
||||||
|
and saml_attributes.get(transient_federation_attribute)):
|
||||||
|
name_id = saml_attributes[transient_federation_attribute]
|
||||||
|
if not isinstance(name_id, basestring):
|
||||||
|
if len(name_id) == 1:
|
||||||
|
name_id = name_id[0]
|
||||||
|
else:
|
||||||
|
self.logger.warning('more than one value for attribute %r, cannot federate',
|
||||||
|
transient_federation_attribute)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
name_id = saml_attributes['name_id_content']
|
||||||
issuer = saml_attributes['issuer']
|
issuer = saml_attributes['issuer']
|
||||||
try:
|
try:
|
||||||
return User.objects.get(saml_identifiers__name_id=name_id,
|
return User.objects.get(saml_identifiers__name_id=name_id,
|
||||||
|
|
|
@ -32,6 +32,7 @@ class AppSettings(object):
|
||||||
'OPENED_SESSION_COOKIE_DOMAIN': None,
|
'OPENED_SESSION_COOKIE_DOMAIN': None,
|
||||||
'ORGANIZATION': None,
|
'ORGANIZATION': None,
|
||||||
'CONTACT_PERSONS': [],
|
'CONTACT_PERSONS': [],
|
||||||
|
'TRANSIENT_FEDERATION_ATTRIBUTE': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import threading
|
import threading
|
||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
|
import lasso
|
||||||
|
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
@ -14,6 +15,7 @@ idp = {
|
||||||
'METADATA': file('tests/metadata.xml').read(),
|
'METADATA': file('tests/metadata.xml').read(),
|
||||||
}
|
}
|
||||||
saml_attributes = {
|
saml_attributes = {
|
||||||
|
'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
|
||||||
'name_id_content': 'x' * 32,
|
'name_id_content': 'x' * 32,
|
||||||
'issuer': 'https://cresson.entrouvert.org/idp/saml2/metadata',
|
'issuer': 'https://cresson.entrouvert.org/idp/saml2/metadata',
|
||||||
'username': ['foobar'],
|
'username': ['foobar'],
|
||||||
|
@ -164,3 +166,27 @@ def test_provision_long_attribute(settings, django_user_model, caplog):
|
||||||
assert 'to value %r ' % (u'y' * 30) in caplog.text()
|
assert 'to value %r ' % (u'y' * 30) in caplog.text()
|
||||||
assert 'set field last_name' in caplog.text()
|
assert 'set field last_name' in caplog.text()
|
||||||
assert 'set field email' in caplog.text()
|
assert 'set field email' in caplog.text()
|
||||||
|
|
||||||
|
|
||||||
|
def test_lookup_user_transient_with_email(private_settings):
|
||||||
|
private_settings.MELLON_TRANSIENT_FEDERATION_ATTRIBUTE = 'email'
|
||||||
|
User = auth.get_user_model()
|
||||||
|
adapter = DefaultAdapter()
|
||||||
|
saml_attributes2 = saml_attributes.copy()
|
||||||
|
saml_attributes2['name_id_format'] = lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
user = adapter.lookup_user(idp, saml_attributes2)
|
||||||
|
assert user is not None
|
||||||
|
assert user.saml_identifiers.count() == 1
|
||||||
|
assert user.saml_identifiers.first().name_id == saml_attributes2['email'][0]
|
||||||
|
|
||||||
|
user2 = adapter.lookup_user(idp, saml_attributes2)
|
||||||
|
assert user.id == user2.id
|
||||||
|
|
||||||
|
User.objects.all().delete()
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
|
||||||
|
private_settings.MELLON_PROVISION = False
|
||||||
|
user = adapter.lookup_user(idp, saml_attributes)
|
||||||
|
assert user is None
|
||||||
|
assert User.objects.count() == 0
|
||||||
|
|
Loading…
Reference in New Issue