iMerica / dj-rest-auth

Authentication for Django Rest Framework
https://dj-rest-auth.readthedocs.io/en/latest/index.html
MIT License
1.66k stars 309 forks source link

post_signup never being called #547

Open hugobessa opened 1 year ago

hugobessa commented 1 year ago

Issue

While we have a post_signup method in the SocialLoginSerializer, it is never called.

Root cause:

This happens because the check that verifies the social account isn't existing is wrong.

The issue is related to the fact that the is_existing attribute we use from the SocialLogin model is actually a property, and it only checks if the pk attribute is defined. As we call the complete_social_login function before the check, the pk of the SocialLogin is always defined at that point.

Possible Solution:

        try:
            if adapter.provider_id == 'google' and not code:
                login = self.get_social_login(adapter, app, social_token, response={'id_token': token})
            else:
                login = self.get_social_login(adapter, app, social_token, token)
        except HTTPError:
            raise serializers.ValidationError(_('Incorrect value'))

        # making a copy is necessary because complete_social_login requires login to not have been
        # looked up previously
        login_copy = deepcopy(login)
        login_copy.lookup()
        should_run_post_signup = False
        if not login_copy.is_existing:
            # We have an account already signed up in a different flow
            # with the same email address: raise an exception.
            # This needs to be handled in the frontend. We can not just
            # link up the accounts due to security constraints
            if allauth_account_settings.UNIQUE_EMAIL:
                # Do we have an account already with this email address?
                account_exists = get_user_model().objects.filter(
                    email=login_copy.user.email,
                ).exists()
                if account_exists:
                    raise serializers.ValidationError(
                        _('User is already registered with this e-mail address.'),
                    )
            should_run_post_signup = True
        ret = complete_social_login(request, login)

        if isinstance(ret, HttpResponseBadRequest):
            raise serializers.ValidationError(ret.content)

        if should_run_post_signup:
            self.post_signup(login, attrs)