8
votes

I'm using both python-social-auth and email registration in my project. For the user model I use a subclass of AbstractBaseUser:

class User(AbstractBaseUser):
    USERNAME_FIELD = 'email'


AUTH_USER_MODEL = 'userprofile.User'

But when a user that is registered with his email ([email protected]) and password tries to login with his Facebook account that is associated with the same email address, I get the following error:

IntegrityError at /social/complete/facebook/
duplicate key value violates unique constraint "userprofile_user_email_key"
DETAIL:  Key (email)=([email protected]) already exists.

/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/core/handlers/base.py in get_response
                    response = wrapped_callback(request, *callback_args, **callback_kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/views/decorators/csrf.py in wrapped_view
        return view_func(*args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/apps/django_app/utils.py in wrapper
            return func(request, backend, *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/apps/django_app/views.py in complete
                       redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/actions.py in do_complete
                                 *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/strategies/base.py in complete
        return self.backend.auth_complete(*args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/backends/facebook.py in auth_complete
        return self.do_auth(access_token, response, *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/backends/facebook.py in do_auth
        return self.strategy.authenticate(*args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/strategies/django_strategy.py in authenticate
        return authenticate(*args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/contrib/auth/__init__.py in authenticate
            user = backend.authenticate(**credentials) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/backends/base.py in authenticate
        return self.pipeline(pipeline, *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/backends/base.py in pipeline
        out = self.run_pipeline(pipeline, pipeline_index, *args, **kwargs) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/backends/base.py in run_pipeline
            result = func(*args, **out) or {} ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/pipeline/user.py in user_details
            strategy.storage.user.changed(user) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/social/storage/django_orm.py in changed
        user.save() ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/base.py in save
                       force_update=force_update, update_fields=update_fields) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/base.py in save_base
            updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/base.py in _save_table
                                      forced_update) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/base.py in _do_update
        return filtered._update(values) > 0 ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/query.py in _update
        return query.get_compiler(self.db).execute_sql(None) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/sql/compiler.py in execute_sql
        cursor = super(SQLUpdateCompiler, self).execute_sql(result_type) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/models/sql/compiler.py in execute_sql
        cursor.execute(sql, params) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/debug_toolbar/panels/sql/tracking.py in execute
        return self._record(self.cursor.execute, sql, params) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/debug_toolbar/panels/sql/tracking.py in _record
            return method(sql, params) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/backends/util.py in execute
            return super(CursorDebugWrapper, self).execute(sql, params) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/backends/util.py in execute
                return self.cursor.execute(sql, params) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/utils.py in __exit__
                six.reraise(dj_exc_type, dj_exc_value, traceback) ...
/Users/vera/.virtualenvs/app/lib/python2.7/site-packages/django/db/backends/util.py in execute
                return self.cursor.execute(sql, params) ...

When somebody registers with his Facebook account and then logs in everything works fine. The problem appears when he registers with his email (I'm using django-registration), so we have an instance of User (but not UserSocialAuth), and then we tries to login with his Facebook account associated the same email address.

1

1 Answers

13
votes

Problem solved. The issue was about the order in pipeline that has to be the following:

DEFAULT_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.mail.mail_validation',
    'social.pipeline.social_auth.associate_by_email',
    'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details'
)

Many thanks for the author of the library who helped to figure this out.