create_user returns an existing non-social user account
See original GitHub issueI’m new to PSA so forgive me if this is silly.
I’m working on a site where we want to handle the case of a user trying to login with a social account, when a non-social account does not already exist with that associated email.
I started with a stock pipeline with the relevant config:
...
# Associates the current social details with another user account with
# a similar email address. Disabled by default.
# 'social_core.pipeline.social_auth.associate_by_email',
# Create a user account if we haven't found one yet.
'social_core.pipeline.user.create_user',
# Create the record that associates the social account with the user.
# this only works if create_user or associate_by_email returns a user
'social_core.pipeline.social_auth.associate_user',
...
My understanding is that 'social_core.pipeline.user.create_user'
will create a new User
if one does not exist, but should not return one if one did not exist. If this unsafe behavior was desired, one could enable 'social_core.pipeline.social_auth.associate_by_email'
.
The problem I’m facing is that create_user
does in fact return an existing user, thus allowing someone with a social account (with an unverified email address) to effectively take over a legit non-social account.
I tracked this behavior down to this code: https://github.com/python-social-auth/social-app-django/blob/master/social_django/storage.py#L90
which has a comment stating:
# User might have been created on a different thread, try and find them.
# If we don't, re-raise the IntegrityError.
It seems to me that a fix for a multi-threading issue may have opened up some unintended security consequences.
Reproduction steps:
- Create a normal user using
./manage.py createsuperuser
that has the same email as a social account - Login with a social auth provider (I’m testing with google oauth2)
- See that login succeeds and that a row now exists in
social_auth_usersocialauth
table
expected behavior:
An error about a failed login.
Versions:
social-auth-app-django 3.1.0
social-auth-core 3.2.0
Issue Analytics
- State:
- Created 4 years ago
- Comments:9 (2 by maintainers)
Top GitHub Comments
We do it pretty much this way in Weblate (the above is just a portion of code around that). On the other side we enforce unique e-mails so users really do not have an option to create another account with e-mail which is already associated elsewhere…
The python-social-auth behavior built-in behavior is that when the user is authenticated it creates additional association with the current user.
In Weblate we deal with this by showing confirmation and asking for user password to confirm this: https://github.com/WeblateOrg/weblate/blob/c770bf8130d4e2484d1872c51abdf2b1ea6aa2b4/weblate/accounts/pipeline.py#L79-L95