auth_fc: handle case of multiple FranceConnect accounts with same email (#53409)
This commit is contained in:
parent
86219adc82
commit
7f8353561d
|
@ -24,7 +24,7 @@ from django.contrib.auth import get_user_model
|
|||
from django.contrib.auth.views import update_session_auth_hash
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import IntegrityError
|
||||
from django.db import IntegrityError, transaction
|
||||
from django.forms import Form
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.urls import reverse
|
||||
|
@ -387,6 +387,17 @@ class LoginOrLinkView(View):
|
|||
% email,
|
||||
)
|
||||
return None
|
||||
if not created and user.fc_accounts.exists():
|
||||
messages.warning(
|
||||
request,
|
||||
_(
|
||||
'Your FranceConnect email address "%s" is already used by the '
|
||||
'FranceConnect account of "%s", so we cannot create an account for you. Please create '
|
||||
'an account with another email address then link it to FranceConnect '
|
||||
'using your account management page.'
|
||||
)
|
||||
% (email, user.get_full_name()),
|
||||
)
|
||||
else: # no email, we cannot disembiguate users, let's create it anyway
|
||||
user = User.objects.create()
|
||||
created = True
|
||||
|
@ -396,13 +407,17 @@ class LoginOrLinkView(View):
|
|||
user.set_unusable_password()
|
||||
user.save()
|
||||
|
||||
models.FcAccount.objects.create(
|
||||
user=user,
|
||||
sub=sub,
|
||||
order=0,
|
||||
token=json.dumps(token),
|
||||
user_info=json.dumps(user_info),
|
||||
)
|
||||
# As we intercept IntegrityError and we can never be sure if we are
|
||||
# in a transaction or not, we must use one to prevent later SQL
|
||||
# queries to fail.
|
||||
with transaction.atomic():
|
||||
models.FcAccount.objects.create(
|
||||
user=user,
|
||||
sub=sub,
|
||||
order=0,
|
||||
token=json.dumps(token),
|
||||
user_info=json.dumps(user_info),
|
||||
)
|
||||
except IntegrityError:
|
||||
# uniqueness check failed, as the user is new, it can only mean that the sub is not unique
|
||||
# let's try again
|
||||
|
|
|
@ -28,6 +28,7 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit as OU
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.journal.models import Event
|
||||
from authentic2.custom_user.models import DeletedUser
|
||||
|
@ -550,3 +551,26 @@ def test_registration_page(settings, app, franceconnect, hooks):
|
|||
|
||||
# hook must have been called
|
||||
assert hooks.calls['event'][0]['kwargs']['name'] == 'fc-create'
|
||||
|
||||
|
||||
def test_same_email_different_sub(app, franceconnect):
|
||||
OU.objects.all().update(email_is_unique=True)
|
||||
|
||||
assert User.objects.count() == 0
|
||||
franceconnect.callback_params = {}
|
||||
|
||||
franceconnect.login_with_fc_fixed_params(app)
|
||||
|
||||
# ok user created
|
||||
assert User.objects.count() == 1
|
||||
# logout
|
||||
app.session.flush()
|
||||
|
||||
# change sub
|
||||
franceconnect.sub = '4567'
|
||||
|
||||
resp = franceconnect.login_with_fc_fixed_params(app).maybe_follow()
|
||||
|
||||
# email collision, sub is different, no new user created
|
||||
assert User.objects.count() == 1
|
||||
assert 'another email address' in resp
|
||||
|
|
Loading…
Reference in New Issue