From 4f98be3a416e7c7731b1190ebfd41633f9bfba18 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 26 Aug 2021 11:16:26 +0200 Subject: [PATCH] auth_oidc: ignore email case when linking existing users (#56392) --- src/authentic2_auth_oidc/backends.py | 4 ++-- tests/test_auth_oidc.py | 33 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/authentic2_auth_oidc/backends.py b/src/authentic2_auth_oidc/backends.py index 986af248..2cf34379 100644 --- a/src/authentic2_auth_oidc/backends.py +++ b/src/authentic2_auth_oidc/backends.py @@ -257,9 +257,9 @@ class OIDCBackend(ModelBackend): if provider.strategy == models.OIDCProvider.STRATEGY_CREATE: try: if app_settings.A2_EMAIL_IS_UNIQUE and email: - user = User.objects.get(email=email) + user = User.objects.get(email__iexact=email) elif provider.ou and provider.ou.email_is_unique: - user = User.objects.get(ou=provider.ou, email=email) + user = User.objects.get(ou=provider.ou, email__iexact=email) linked = True except User.DoesNotExist: pass diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index b32c7b38..e508e12a 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -39,6 +39,7 @@ from authentic2.a2_rbac.utils import get_default_ou from authentic2.custom_user.models import DeletedUser from authentic2.models import Attribute, AttributeValue from authentic2.utils.misc import last_authentication_event +from authentic2_auth_oidc.backends import OIDCBackend from authentic2_auth_oidc.models import OIDCAccount, OIDCClaimMapping, OIDCProvider from authentic2_auth_oidc.utils import ( IDToken, @@ -944,3 +945,35 @@ def test_strategy_find_username(app, caplog, code, oidc_provider, oidc_provider_ with utils.check_log(caplog, 'found user using username'): with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, nonce=nonce): response = app.get(login_callback_url(oidc_provider), params={'code': code, 'state': state}) + + +def test_link_by_email(app, caplog, code): + oidc_provider = make_oidc_provider(idtoken_algo=OIDCProvider.ALGO_HMAC) + ou = get_default_ou() + ou.email_is_unique = True + ou.save() + + user = User.objects.create(ou=ou, email='john.doe@example.com') + assert User.objects.count() == 1 + assert OIDCAccount.objects.count() == 0 + + response = app.get('/').maybe_follow() + assert oidc_provider.name in response.text + response = response.click(oidc_provider.name) + location = urllib.parse.urlparse(response.location) + query = QueryDict(location.query) + state = query['state'] + nonce = query['nonce'] + + with oidc_provider_mock( + oidc_provider, + oidc_provider_jwkset, + code, + nonce=nonce, + extra_user_info={'email': 'JOHN.DOE@examplE.COM'}, + ): + response = app.get(login_callback_url(oidc_provider), params={'code': code, 'state': state}) + + assert app.session['_auth_user_id'] == str(user.id) + assert User.objects.count() == 1 + assert OIDCAccount.objects.count() == 1 -- 2.32.0.rc0