383 lines
13 KiB
Python
383 lines
13 KiB
Python
import datetime
|
|
|
|
import lasso
|
|
import pytest
|
|
from authentic2.a2_rbac.utils import get_default_ou
|
|
from authentic2.models import Attribute
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth.models import AnonymousUser
|
|
from django.contrib.messages.middleware import MessageMiddleware
|
|
from django.contrib.sessions.middleware import SessionMiddleware
|
|
from django.db import connection
|
|
from django.db.migrations.executor import MigrationExecutor
|
|
from django.test.client import RequestFactory
|
|
from mellon.models import Issuer, UserSAMLIdentifier
|
|
from utils import login
|
|
|
|
from authentic2_auth_fedict.adapters import AuthenticAdapter
|
|
from authentic2_auth_fedict.backends import FedictBackend
|
|
from authentic2_auth_fedict.models import FedictAuthenticator
|
|
|
|
User = get_user_model()
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
factory = RequestFactory()
|
|
|
|
|
|
@pytest.fixture
|
|
def authenticator():
|
|
return FedictAuthenticator.objects.create(slug='fedict', enabled=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def adapter():
|
|
return AuthenticAdapter()
|
|
|
|
|
|
@pytest.fixture
|
|
def idp_conf():
|
|
return {
|
|
'A2_ATTRIBUTE_MAPPING': [
|
|
{
|
|
'attribute': 'email',
|
|
'saml_attribute': 'mail',
|
|
},
|
|
{
|
|
'attribute': 'last_name',
|
|
'saml_attribute': 'surname',
|
|
},
|
|
{
|
|
'attribute': 'first_name',
|
|
'saml_attribute': 'givenName',
|
|
},
|
|
{
|
|
'attribute': 'uuid',
|
|
'saml_attribute': 'urn:be:fedict:iam:attr:fedid',
|
|
},
|
|
]
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def issuer():
|
|
return Issuer.objects.create(entity_id='https://idp.com/', slug='idp')
|
|
|
|
|
|
@pytest.fixture
|
|
def fedict_attributes():
|
|
return {
|
|
'issuer': 'https://idp.com/',
|
|
'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED,
|
|
'surname': ['Doe'],
|
|
'givenName': ['John'],
|
|
'mail': ['john.doe@example.org'],
|
|
'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
|
|
}
|
|
|
|
|
|
def test_custom_lookup_user(adapter, idp_conf, issuer, fedict_attributes):
|
|
assert User.objects.count() == 0
|
|
|
|
user = adapter.lookup_user(idp_conf, fedict_attributes)
|
|
user.refresh_from_db()
|
|
assert user.email == '' # email purposely deleted
|
|
assert user.first_name == '' # not provisionned yet
|
|
assert user.last_name == '' # not provisionned yet
|
|
assert user.username == 'c54db0a8ddc24a02a2d057f857d3b102@saml' # <NameID>@<source>
|
|
assert user.ou == get_default_ou()
|
|
|
|
|
|
def test_login_fedict_authenticator_displayed(app, settings, issuer, authenticator):
|
|
response = app.get('/login/')
|
|
assert 'Belgian eID' in response
|
|
assert 'csam-login' in response
|
|
|
|
|
|
def test_authenticate_eid_provision(app, settings, issuer):
|
|
backend = FedictBackend()
|
|
request = factory.get(path='/accounts/')
|
|
request.user = AnonymousUser()
|
|
|
|
saml_attributes = {
|
|
'city': [],
|
|
'zipcode': [],
|
|
'givenName': ['Doe'],
|
|
'surname': ['John'],
|
|
'verified_attributes': [],
|
|
'address': [],
|
|
'last_name': ['Doe'],
|
|
'first_name': ['John'],
|
|
'title': [],
|
|
'username': ['john.doe'],
|
|
'urn:be:fedict:iam:attr:fedid': ['xyz'], # new fedict id
|
|
'is_superuser': ['false'],
|
|
'phone': [],
|
|
'mobile': [],
|
|
'issuer': 'https://idp.com/',
|
|
'nonce': None,
|
|
'force_authn': False,
|
|
'name_id_content': 'xyz', # new fedict id
|
|
'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
|
|
'authn_instant': datetime.datetime(2022, 1, 27, 11, 26, 7, 301054),
|
|
'session_not_on_or_after': datetime.datetime(2022, 1, 27, 16, 26, 7),
|
|
'session_index': '_401EEEE3C700B6D203B83AA1826E3B80',
|
|
'authn_context_class_ref': 'urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
|
|
'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
}
|
|
credentials = {'saml_attributes': saml_attributes}
|
|
|
|
assert len(User.objects.all()) == 0
|
|
SessionMiddleware().process_request(request)
|
|
MessageMiddleware().process_request(request)
|
|
backend_user = backend.authenticate(request, **credentials)
|
|
assert backend_user.is_authenticated
|
|
assert backend_user.username == 'xyz@saml' # <NameID>@<source>
|
|
|
|
|
|
def test_authenticate_eid_link_to_existing_user(app, settings, issuer, user):
|
|
backend = FedictBackend()
|
|
request = factory.get(path='/accounts/')
|
|
request.user = user
|
|
|
|
UserSAMLIdentifier.objects.create(
|
|
user=user,
|
|
name_id='c54db0a8ddc24a02a2d057f857d3b102',
|
|
issuer=Issuer.objects.first(),
|
|
)
|
|
|
|
saml_attributes = {
|
|
'city': [],
|
|
'zipcode': [],
|
|
'givenName': ['Doe'],
|
|
'surname': ['John'],
|
|
'verified_attributes': [],
|
|
'address': [],
|
|
'last_name': ['Doe'],
|
|
'first_name': ['John'],
|
|
'title': [],
|
|
'username': ['john.doe'],
|
|
'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
|
|
'is_superuser': ['false'],
|
|
'phone': [],
|
|
'mobile': [],
|
|
'issuer': 'https://idp.com/',
|
|
'nonce': None,
|
|
'force_authn': False,
|
|
'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
|
|
'authn_instant': datetime.datetime(2022, 1, 27, 11, 26, 7, 301054),
|
|
'session_not_on_or_after': datetime.datetime(2022, 1, 27, 16, 26, 7),
|
|
'session_index': '_401EEEE3C700B6D203B83AA1826E3B80',
|
|
'authn_context_class_ref': 'urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
|
|
'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
}
|
|
credentials = {'saml_attributes': saml_attributes}
|
|
|
|
SessionMiddleware().process_request(request)
|
|
MessageMiddleware().process_request(request)
|
|
backend_user = backend.authenticate(request, **credentials)
|
|
assert backend_user == user
|
|
|
|
|
|
def test_eid_unlink(app, settings, issuer, user, authenticator):
|
|
assert len(UserSAMLIdentifier.objects.all()) == 0
|
|
|
|
# create link
|
|
UserSAMLIdentifier.objects.create(
|
|
user=user,
|
|
name_id='abc',
|
|
issuer=Issuer.objects.first(),
|
|
)
|
|
|
|
response = login(app, user, path='/accounts/', password=user.username)
|
|
assert 'Unlink my account' in response.text
|
|
app.get('/accounts/fedict/unlink/').follow()
|
|
|
|
response = app.get('/accounts/')
|
|
assert 'Link my account to my eID card' in response.text
|
|
|
|
|
|
def test_provision_new_attributes_verified(app, settings, issuer, user):
|
|
Attribute.objects.create(name='title', kind='title', label='Titre')
|
|
# email & title verified
|
|
user.email = 'john.doe@verified.publik.love'
|
|
user.email_verified = True
|
|
user.verified_attributes.title = 'Mr'
|
|
user.first_name = 'Johnny'
|
|
user.last_name = 'Smith'
|
|
user.save()
|
|
UserSAMLIdentifier.objects.create(
|
|
user=user,
|
|
name_id='c54db0a8ddc24a02a2d057f857d3b102',
|
|
issuer=Issuer.objects.first(),
|
|
)
|
|
|
|
backend = FedictBackend()
|
|
request = factory.get(path='/accounts/')
|
|
request_user = User.objects.create(
|
|
first_name='Foo',
|
|
last_name='Bar',
|
|
email='foo.bar@nowhere.null',
|
|
)
|
|
request.user = request_user
|
|
saml_attributes = {
|
|
'givenName': ['Doe'],
|
|
'surname': ['John'],
|
|
'last_name': ['Doe'],
|
|
'first_name': ['John'],
|
|
'username': ['john.doe'],
|
|
'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
|
|
'is_superuser': ['false'],
|
|
'issuer': 'https://idp.com/',
|
|
'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
|
|
'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
}
|
|
credentials = {'saml_attributes': saml_attributes}
|
|
SessionMiddleware().process_request(request)
|
|
MessageMiddleware().process_request(request)
|
|
backend_user = backend.authenticate(request, **credentials)
|
|
assert backend_user == request_user
|
|
assert backend_user.email == 'john.doe@verified.publik.love'
|
|
assert backend_user.email_verified == True
|
|
assert backend_user.verified_attributes.title == 'Mr'
|
|
assert backend_user.first_name == 'Foo'
|
|
assert backend_user.last_name == 'Bar'
|
|
|
|
|
|
def test_missing_title_attribute(app, settings, issuer, user):
|
|
Attribute.objects.filter(kind='title').delete()
|
|
# email & title verified
|
|
user.email = 'john.doe@verified.publik.love'
|
|
user.email_verified = True
|
|
user.first_name = 'Johnny'
|
|
user.last_name = 'Smith'
|
|
user.save()
|
|
UserSAMLIdentifier.objects.create(
|
|
user=user,
|
|
name_id='c54db0a8ddc24a02a2d057f857d3b102',
|
|
issuer=Issuer.objects.first(),
|
|
)
|
|
|
|
backend = FedictBackend()
|
|
request = factory.get(path='/accounts/')
|
|
request_user = User.objects.create(
|
|
first_name='Foo',
|
|
last_name='Bar',
|
|
email='foo.bar@nowhere.null',
|
|
)
|
|
request.user = request_user
|
|
saml_attributes = {
|
|
'givenName': ['Doe'],
|
|
'surname': ['John'],
|
|
'last_name': ['Doe'],
|
|
'first_name': ['John'],
|
|
'username': ['john.doe'],
|
|
'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
|
|
'egovNRN': ['85073003328'],
|
|
'is_superuser': ['false'],
|
|
'issuer': 'https://idp.com/',
|
|
'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
|
|
'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
}
|
|
credentials = {'saml_attributes': saml_attributes}
|
|
SessionMiddleware().process_request(request)
|
|
MessageMiddleware().process_request(request)
|
|
backend_user = backend.authenticate(request, **credentials)
|
|
assert backend_user == request_user
|
|
|
|
|
|
def test_provision_old_account_deleted(app, settings, issuer, user):
|
|
backend = FedictBackend()
|
|
request = factory.get(path='/accounts/')
|
|
request_user = User.objects.create(
|
|
first_name='foo',
|
|
last_name='bar',
|
|
email='foo.bar@nowhere.null',
|
|
)
|
|
request.user = request_user
|
|
count = User.objects.count()
|
|
user_uuid = user.uuid
|
|
UserSAMLIdentifier.objects.create(
|
|
user=user,
|
|
name_id='c54db0a8ddc24a02a2d057f857d3b102',
|
|
issuer=Issuer.objects.first(),
|
|
)
|
|
saml_attributes = {
|
|
'givenName': ['Doe'],
|
|
'surname': ['John'],
|
|
'last_name': ['Doe'],
|
|
'first_name': ['John'],
|
|
'username': ['john.doe'],
|
|
'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
|
|
'is_superuser': ['false'],
|
|
'issuer': 'https://idp.com/',
|
|
'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
|
|
'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
|
|
}
|
|
credentials = {'saml_attributes': saml_attributes}
|
|
|
|
SessionMiddleware().process_request(request)
|
|
MessageMiddleware().process_request(request)
|
|
backend_user = backend.authenticate(request, **credentials)
|
|
# link has been created on currently logged-in user
|
|
assert backend_user == request_user
|
|
# previous user as been deactivated
|
|
assert User.objects.count() == count - 1
|
|
assert not User.objects.filter(uuid=user_uuid)
|
|
|
|
|
|
def test_fedict_authenticator_data_migration(settings):
|
|
app = 'authentic2_auth_fedict'
|
|
migrate_from = [(app, '0001_initial')]
|
|
migrate_to = [(app, '0002_auto_20220706_1712')]
|
|
|
|
executor = MigrationExecutor(connection)
|
|
old_apps = executor.loader.project_state(migrate_from).apps
|
|
executor.migrate(migrate_from)
|
|
FedictAuthenticator = old_apps.get_model(app, 'FedictAuthenticator')
|
|
|
|
settings.AUTH_FRONTENDS_KWARGS = {
|
|
'fedict': {'priority': 3, 'show_condition': "'backoffice' not in login_hint"}
|
|
}
|
|
settings.A2_AUTH_FEDICT_ENABLE = True
|
|
|
|
executor = MigrationExecutor(connection)
|
|
executor.migrate(migrate_to)
|
|
executor.loader.build_graph()
|
|
new_apps = executor.loader.project_state(migrate_to).apps
|
|
FedictAuthenticator = new_apps.get_model(app, 'FedictAuthenticator')
|
|
|
|
authenticator = FedictAuthenticator.objects.get()
|
|
assert authenticator.slug == 'fedict-authenticator'
|
|
assert authenticator.order == 3
|
|
assert authenticator.show_condition == "'backoffice' not in login_hint"
|
|
assert authenticator.enabled is True
|
|
|
|
|
|
def test_manager(app, admin):
|
|
resp = login(app, admin, path='/manage/authenticators/', index=0)
|
|
|
|
resp = resp.click('Add new authenticator')
|
|
resp.form['authenticator'] = 'fedict'
|
|
resp = resp.form.submit().follow()
|
|
|
|
authenticator = FedictAuthenticator.objects.get()
|
|
assert not authenticator.enabled
|
|
|
|
# on edit page, submit
|
|
resp = resp.form.submit().follow()
|
|
resp = resp.click('Enable')
|
|
|
|
authenticator.refresh_from_db()
|
|
assert authenticator.enabled
|