In my website it is possible to login through:
- username and password
- e-mail and password
- google auth 2
Where I am using django user built in system and python social auth.
The problem:
Suppose I create the following account:
username: losimonassi e-mail: lorenzosimonassi@gmail.com
Then when I try to login with my gmail (lorenzosimonassi@gmail.com) python social auth creates another user with the same e-mail. So, when I try to login using my e-mail the auth system finds two similar e-mails which raises an error.
I am trying to find a way that when the user try to login with gmail his e-mail is checked against the DB and if it already exists the process is stopped with a redirect and a alert message (I think it could be made through the middleware).
But of course the checking against the DB should only check against other backends users and normal users, to avoid blocking his own login.
I don't want to associate the accounts.
settings.py
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.user.create_user',
#'social.pipeline.social_auth.associate_user',
#'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
You can choose to associate users by their email addresses by adding a built-in, but by default not active step in the pipeline. Note that you should only do this if you are certain that the social provider verifies the email addresses. Otherwise I could sign up to a social provider using your email, login to your site and have access to your user on your site.
Python social auth docs and how to associate user by email: https://python-social-auth-docs.readthedocs.io/en/latest/use_cases.html?highlight=associate%20user#associate-users-by-email
From the above link:
EDIT: As noted by Jack in the comments, the order of the pipeline steps are important.
I have encountered the situation you describe. Way I solved it: add custom step to social auth pipeline:
Add your callable to the pipeline:
Raising
AuthException
will redirect user to yoursettings.SOCIAL_AUTH_LOGIN_ERROR_URL
. However, if that is not what you want, there also is another approach. Python-social-auth checks return value of any part of your pipeline. If return value isNone
, it just proceeds. If it is adict
, it will update kwargs using that dictionary so that the values are available later in the pipeline. However, if the return value isHttpResponse
, say,HttpResponseRedirect
, it will return that response to the user. So, instead of raising anAuthException
, you can doHowever, do take that with a grain of salt: the docs don't state this clearly and I have done this quite some time ago, so I might be mistaken.