Open dperetti opened 6 years ago
You are absolutely right, it doesn't connect same social email addresses, I went through the code and l realized that, connect=True is actually not used in Allauth https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py#L238 and rest auth relies on this from this line of code https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/serializers.py#L143 . And this creates duplicates accounts with same email address in the Django user table from this line of code https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py#L231. This is problematic. I am currently looking at a way to fix this in my code
I managed to make it work. I am sharing my code so that it will help someone Edit this line of code https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/serializers.py#L127 with
if not login.is_existing:
if allauth_settings.UNIQUE_EMAIL:# Application enforces UNQIUE EMAIL
# Do we have an account already with this email address?
account_exists = get_user_model().objects.filter(email=login.user.email,).exists()
if account_exists:#Yes we do
#Grab the user for existing email address
get_exisiting_user=get_user_model().objects.filter(email=login.user.email,).first()
login.account.user = get_exisiting_user #Set the exisiting user to this Allauth social login object
login.account.save()#Save Allauth Social Login Object
from allauth.socialaccount import app_settings
if app_settings.STORE_TOKENS and login.token:
login.token.account = login.account #Set Allauth social login object to Allauth Social Application Token Object
login.token.save()
else:#Account doesn't exist with this email address, let Allauth deal with normal creation of user account and linking of user to Allauth social login object
login.lookup()
login.save(request, connect=True)
Let me know if that helped. It is working perfectly for me
My approach was eventually to override perform_create()
in RegisterView
:
class EmailRegisterView(RegisterView):
"""
Override rest_auth's email RegisterView in order to fix a major flaw where a user authenticated with Facebook
cannot link up an email account.
See also core.serializers.RegisterSerializer for another fix.
"""
def perform_create(self, serializer):
# fix start
# If the user is already authenticated (because the API was called using the JWT token), we want
# to associate this new email to the existing account, not create a separate account.
if self.request.user and self.request.user.is_authenticated:
user: User = self.request.user
email = serializer.validated_data['email']
password = serializer.validated_data['password1']
user.email = email
user.set_password(password)
user.save()
sync_user_email_addresses(user)
# fix end
else:
user = serializer.save(self.request)
if getattr(settings, 'REST_USE_JWT', False):
self.token = jwt_encode(user)
else:
create_token(self.token_model, user, serializer)
complete_signup(self.request._request, user, allauth_settings.EMAIL_VERIFICATION, None)
return user
And in urls.py
:
path('rest-auth/registration/', EmailRegisterView.as_view(), name='rest_register'),
path('rest-auth/registration/', include('rest_auth.registration.urls')),
Expected
1) I sign up with FB at
/rest-auth/facebook/
. I get a JWT token. 2) I register an email at/rest-auth/registration
, using the Bearer token in the header to get authorized. 3) The email is associated to my account.Actual results
The bearer token is ignored and another account is created.
Issue
The strength of django-allauth is the ability to associate multiple social accounts / email in a single account. I may be missing something, but this doesn't seem possible with django-rest-auth ?