2

My app uses both email registration and Facebook or Google+ registration using python-social-auth (0.2.11). When some new users register using Facebook, they are taken to an error page. After that, I see the following error:

Internal Server Error: /complete/facebook/
Traceback (most recent call last):
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/newrelic/hooks/framework_django.py", line 527, in wrapper
    return wrapped(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/apps/django_app/utils.py", line 51, in wrapper
    return func(request, backend, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/apps/django_app/views.py", line 28, in complete
    redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/actions.py", line 43, in do_complete
    user = backend.complete(user=user, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/base.py", line 41, in complete
    return self.auth_complete(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/utils.py", line 229, in wrapper
    return func(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/facebook.py", line 87, in auth_complete
    return self.do_auth(access_token, response, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/facebook.py", line 119, in do_auth
    return self.strategy.authenticate(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/strategies/django_strategy.py", line 96, in authenticate
    return authenticate(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/auth/__init__.py", line 74, in authenticate
    user = backend.authenticate(**credentials)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/base.py", line 82, in authenticate
    return self.pipeline(pipeline, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/base.py", line 85, in pipeline
    out = self.run_pipeline(pipeline, pipeline_index, *args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/backends/base.py", line 112, in run_pipeline
    result = func(*args, **out) or {}
  File "/app/.heroku/python/lib/python2.7/site-packages/social/pipeline/user.py", line 70, in create_user
    'user': strategy.create_user(**fields)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/strategies/base.py", line 53, in create_user
    return self.storage.user.create_user(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/social/storage/django_orm.py", line 60, in create_user
    return cls.user_model().objects.create_user(*args, **kwargs)
  File "/app/wehealth/users/models.py", line 47, in create_user
    user.save(using=self._db)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py", line 710, in save
    force_update=force_update, update_fields=update_fields)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py", line 738, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py", line 822, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py", line 861, in _do_insert
    using=using, raw=raw)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/query.py", line 920, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 963, in execute_sql
    cursor.execute(sql, params)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/utils.py", line 97, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/app/.heroku/python/lib/python2.7/site-packages/newrelic/hooks/database_dbapi2.py", line 25, in execute
    *args, **kwargs)
IntegrityError: duplicate key value violates unique constraint "users_user_email_key"
DETAIL:  Key (email)=() already exists.

I do not see this error with all new users. For instance, in the past 24hrs, I have received this error at the following times:

  • 13:52, 13:59, 19:32, 19:33, 21:34, 22:13, 22:15, 22:29

However, I have had users successfully register through Facebook at the following times:

  • 17:05, 17:18, 21:41, 21:58, 01:57, 02:20, 02:28, 07:33, 09:50, 10:33, 13:34, 14:07

I don't see any relationship between the users who sign up successfully and those who get errors. I do not believe that this is an issue of existing users trying to sign up using Facebook. I've been notified by a few 1st time users that they've gotten the error.

It appears that the error is occuring within the create_user function. My pipeline is as follows:

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.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',
    'users.pipeline.user.store_gender',
    'users.pipeline.user.store_registration_type',
)

Any idea what could be wrong? Facebook registration is working for me around 70% of the time, but I get this error in the remaining 30%. There doesn't seem to be a pattern to the errors, and it's really throwing me for a loop. Should I migrate to a different authentication service? I am using Django 1.8 and Python 2.7.

wraasch
  • 405
  • 3
  • 13

1 Answers1

4

The problem is that your email field is unique and you already have a user with '' value, which is an empty string.

What is happening is that when a user is trying to login with Facebook, sometimes email is empty (maybe he did not give a permission to get email from Facebook). Then, when you are trying to save it, it is giving out this error.

To verify this, get the user with empty email and delete him:

user = User.objects.get(email='')
user.delete()

Then, try loging in with Facebook again. There should not be any error. Now try again. You will have this same error.

Hope it helps!

Jahongir Rahmonov
  • 13,083
  • 10
  • 47
  • 91
  • Thank you! So it did turn out that I had one user without an email. I have fixed that user by adding their email since I knew it and didn't want them to lose their data. So are the people who get errors people who are not sharing their email? If so, will they be created with a blank email? – wraasch Aug 29 '17 at 18:04
  • @wraasch correct. They are not sharing their email or for some other reason you are not able to get their email from Facebook. Yes, the first person will have a blank email but with others you will have that error. – Jahongir Rahmonov Aug 29 '17 at 18:05
  • Is there a common pipeline to require email? Or perhaps create a dummy email to avoid the error? I have marked correct btw. Thanks again! – wraasch Aug 29 '17 at 18:09
  • @wraasch You can't require their email as they can always decline permission. You should either reject a user without email or as you said create a random email when an `emailless` person tries to register. – Jahongir Rahmonov Aug 29 '17 at 18:11
  • @JahongirRahmonov is correct, you are getting errors because you allow blank emails in your DB, but still have a unique constraint in your field, possible solutions would be to remove the unique constraint if email is not a required field for your app; or add a custom pipeline to ask for user emails when it's missing. Check the [partial pipeline feature](https://python-social-auth.readthedocs.io/en/latest/pipeline.html#partial-pipeline), also the [example app](https://github.com/python-social-auth/social-examples/blob/master/example-common/pipeline.py) can get you started. – omab Aug 29 '17 at 21:57