diff --git a/src/authentic2_auth_oidc/utils.py b/src/authentic2_auth_oidc/utils.py index 45561f35f..ef9516613 100644 --- a/src/authentic2_auth_oidc/utils.py +++ b/src/authentic2_auth_oidc/utils.py @@ -78,7 +78,10 @@ def parse_id_token(encoded, provider): def resolve_claim_mappings(provider, context, id_token=None, user_info=None): mappings = [] + disabled_attrs = Attribute.all_objects.filter(disabled=True).values_list('name', flat=True) for claim_mapping in provider.claim_mappings.all(): + if claim_mapping.attribute in disabled_attrs: + continue claim = claim_mapping.claim if id_token is None and user_info is None: source = context diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index 0d95429ed..c0af01590 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -25,6 +25,7 @@ from unittest import mock import pytest from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from django.contrib.messages import constants as message_constants from django.core.exceptions import ValidationError from django.db import IntegrityError, transaction @@ -504,6 +505,17 @@ def test_login_autorun(oidc_provider, app, settings): def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, hooks): cassis = OrganizationalUnit.objects.create(name='Cassis', slug='cassis') + # a mapping defined for a later-deactivated attribute should be ignored + attr = Attribute.objects.create(kind='string', name='another_name', label='Another name') + OIDCClaimMapping.objects.create( + authenticator=oidc_provider, + claim='given_name', + required=False, + attribute='another_name', + ) + attr.disabled = True + attr.save() + response = app.get('/admin/').maybe_follow() assert oidc_provider.name in response.text response = response.click(oidc_provider.name) @@ -609,6 +621,9 @@ def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, hooks): assert user.attributes.last_name == 'Doe' assert AttributeValue.objects.filter(content='John', verified=True).count() == 1 assert AttributeValue.objects.filter(content='Doe', verified=False).count() == 1 + assert not AttributeValue.objects.filter( + content_type=ContentType.objects.get_for_model(user), object_id=user.id, attribute=attr + ) assert last_authentication_event(session=app.session)['nonce'] == nonce with oidc_provider_mock( diff --git a/tests/test_manager_authenticators.py b/tests/test_manager_authenticators.py index 1eb3545d3..856e2f98a 100644 --- a/tests/test_manager_authenticators.py +++ b/tests/test_manager_authenticators.py @@ -344,6 +344,22 @@ def test_authenticators_oidc_claims(app, superuser): assert_event('authenticator.related_object.deletion', user=superuser, session=app.session) +def test_authenticators_oidc_claims_disabled_attribute(app, superuser): + authenticator = OIDCProvider.objects.create(slug='idp1') + attr = Attribute.objects.create(kind='string', name='test_attribute', label='Test attribute') + + resp = login(app, superuser, path=authenticator.get_absolute_url()) + resp = resp.click('Add', href='claim') + assert resp.pyquery('select#id_attribute option[value=test_attribute]') + + attr.disabled = True + attr.save() + + resp = app.get(authenticator.get_absolute_url()) + resp = resp.click('Add', href='claim') + assert not resp.pyquery('select#id_attribute option[value=test_attribute]') + + def test_authenticators_oidc_add_role(app, superuser, role_ou1): authenticator = OIDCProvider.objects.create(slug='idp1') resp = login(app, superuser, path=authenticator.get_absolute_url())