Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Twitter backend error with Python 3.3 #139

Closed
fajran opened this issue Jan 3, 2014 · 9 comments
Closed

Twitter backend error with Python 3.3 #139

fajran opened this issue Jan 3, 2014 · 9 comments

Comments

@fajran
Copy link

fajran commented Jan 3, 2014

(Perhaps this also affects all OAuth1 based backends)

I got the following error

b'oauth_token=TOKEN&oauth_token_secret=SECRET&oauth_callback_confirmed=true' is not JSON serializable

The error arises when Django saves the session data (encoded in JSON) that contains that unauthorized token from Twitter. The type of the token is byte so the json module refuses to encode it. I see that the token value is retrieved from the requests module.

Other libs that are also installed in my setup:

$ pip list
Django (1.6)
geojson (1.0.5)
ipython (1.1.0)
lxml (3.2.4)
oauthlib (0.6.0)
pip (1.4.1)
psycopg2 (2.5.1)
pykml (0.1.0)
python-social-auth (0.1.17)
python3-openid (3.0.3)
raven (3.5.2)
requests (2.1.0)
requests-oauthlib (0.3.1)
setuptools (0.9.8)
Shapely (1.2.18)
six (1.4.1)
South (0.8.4)
virtualenv (1.10.1)
@ghost
Copy link

ghost commented Jan 17, 2014

I can confirm - error still there...

Python 3.3.3, Django 1.6.1

Stacktrace (most recent call last):

  File "django/core/handlers/base.py", line 201, in get_response
    response = middleware_method(request, response)
  File "django/contrib/sessions/middleware.py", line 38, in process_response
    request.session.save()
  File "django/contrib/sessions/backends/db.py", line 57, in save
    session_data=self.encode(self._get_session(no_load=must_create)),
  File "django/contrib/sessions/backends/base.py", line 87, in encode
    serialized = self.serializer().dumps(session_dict)
  File "django/core/signing.py", line 88, in dumps
    return json.dumps(obj, separators=(',', ':')).encode('latin-1')
  File "json/__init__.py", line 243, in dumps
    **kw).encode(obj)
  File "json/encoder.py", line 191, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "json/encoder.py", line 249, in iterencode
    return _iterencode(o, 0)
  File "json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")

@omab
Copy link
Owner

omab commented Jan 17, 2014

Could you share your pipelines?

@ghost
Copy link

ghost commented Jan 17, 2014

@omab,

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',
    'bemycobase.pipeline.require_email_username_birthdate_sex_city',
    # 'social.pipeline.mail.mail_validation',
    'bemycobase.pipeline.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details'
)
from datetime import datetime
import traceback
from account.models import EmailAddress
from django.contrib import messages
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from social.pipeline.partial import partial
import sys


@partial
def require_email_username_birthdate_sex_city(strategy, details, user=None,
                                              is_new=False, *args, **kwargs):
    if user and user.email and user.username and user.first_name \
        and user.last_name and user.birthdate and user.sex \
        and user.city:
        return
    elif is_new and (not details.get('email') or not details.get('username')
                     or not details.get('first_name')
                     or not details.get('last_name')
                     or not details.get('birthdate') or not details.get('sex')
                     or not details.get('city_id')):
        if strategy.session_get('saved_email') and \
                strategy.session_get('saved_username') and \
                strategy.session_get('saved_first_name') and \
                strategy.session_get('saved_last_name') and \
                strategy.session_get('saved_birthdate') and \
                strategy.session_get('saved_sex') and \
                strategy.session_get('saved_city_id'):
            details['email'] = strategy.session_pop('saved_email')
            details['username'] = strategy.session_pop('saved_username')
            details['first_name'] = strategy.session_pop('saved_first_name')
            details['last_name'] = strategy.session_pop('saved_last_name')
            details['birthdate'] = strategy.session_pop('saved_birthdate')
            details['sex'] = strategy.session_pop('saved_sex')
            details['city_id'] = strategy.session_pop('saved_city_id')
        else:
            return redirect(
                'bemycobase:require_email_username_birthdate_sex_city')

def create_user(strategy, details, response, uid, user=None, *args, **kwargs):
    if user:
        return

    fields = dict((name, kwargs.get(name) or details.get(name))
                        for name in strategy.setting('USER_FIELDS'))
    if not fields:
        return

    fields['birthdate'] = datetime.strptime(details.get('birthdate'),
                                            '%Y-%m-%d')
    try:
        created_user = strategy.create_user(**fields)  # commit=False,
        # prevent User post_save signal from creating an Account instance
        # we want to handle that ourself.
        # created_user._disable_account_creation = True
        created_user.username = details.get('username')
        created_user.save()
        # created_email = EmailAddress.objects.add_email(created_user,
        #                                                created_user.email,
        #                                                **{'primary': True,
        #                                                   'verified': False,
        #                                                   'confirm': True})
        # Account.create(request=strategy.request, user=created_user,
        # create_email=False)
        email_address = EmailAddress.objects.get(user=created_user,
                                                 email=created_user.email)
        email_address.send_confirmation()
        messages.add_message(
            strategy.request,
            messages.INFO,
            _("Confirmation email sent to {email}.").format(**{
                "email": details.get("email")
            })
        )
        return {
            'is_new': True,
            'user': created_user
        }
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
        debug = ''.join('!! ' + line for line in lines)

@ghost
Copy link

ghost commented Jan 17, 2014

But you can ignore my custom pipelines because of I can't associate my current user account with Twitter too...

@omab
Copy link
Owner

omab commented Jan 17, 2014

@lorddaedra, could you try again with the last reviesion on master?

@ghost
Copy link

ghost commented Jan 17, 2014

@omab tested trunk, it works fine... (before I used latest pip)

@omab
Copy link
Owner

omab commented Jan 17, 2014

Cool, I'm gonna release it. Thanks!

@omab omab closed this as completed Jan 17, 2014
@fajran
Copy link
Author

fajran commented Jan 17, 2014

Thanks!

I used something similar to your fix for a temporary workaround angkot/angkot@b43d07a

@JordanReiter
Copy link
Contributor

I'm getting the same error on Master now, with the Facebook OAuth backend.

JordanReiter added a commit to JordanReiter/python-social-auth that referenced this issue Jul 16, 2015
Right now when you use .content, the token is bytes, not text, and so you run into an error when saving it to the session. Similar error in issue omab#139.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants