4

here's my pipeline in settings.py:

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',
    'accounts.pipeline.create_user',
    'accounts.pipeline.update_user_social_data',
    # 'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details',
)

along with this line:

SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

I tried this as well:

FACEBOOK_EXTENDED_PERMISSIONS = ['email']

and in my pipeline.py:

def create_user(strategy, details, user=None, *args, **kwargs):
    if user:
        return {
            'is_new': False
        }

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

    if not fields:
        return

    if strategy.session_get('signup') == 'UserType1':
        user1 = UserType1.objects.create_user(username=fields.get('username'))
        user1.user_type = User.USERTYPE1
        user1.save()

        return {
            'is_new': True,
            'user': user1
        }

    elif strategy.session_get('signup') == 'UserType2':
        user2 = UserType2.objects.create_user(username=fields.get('username'))
        user2.user_type = User.USERTYPE2
        user2.save()

        return {
            'is_new': True,
            'user': user2
        }


def update_user_social_data(strategy, *args, **kwargs):
    if not kwargs['is_new']:
        return

    full_name = ''
    backend = kwargs['backend']

    user = kwargs['user']

    full_name = kwargs['response'].get('name')
    user.full_name = full_name

    email = kwargs['response'].get('email')
    user.email = email

    user.save()

However, kwargs['response'].get('name') returns user's full name correctly, but kwargs['response'].get('email') is always none. When I do print kwargs['response'], it only shows uid and the name of the user as well, so Facebook doesn't return user's email. How to overcome this? Thanks!

Hasan Can Saral
  • 2,950
  • 5
  • 43
  • 78

3 Answers3

11

I think this might be due to changes in Facebook's Graph API v2.4.

In previous versions of the API, adding

SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

would allow you to get the facebook user's email. Now, that is not sufficient and kwargs['response'].get('email') is blank.

However, as explained in python social auth issue 675, also adding this

SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
    'fields': 'id,name,email', 
}

to your settings seems to get around this problem and you can get the user's email again.

mjandrews
  • 2,392
  • 4
  • 22
  • 39
  • 1
    It is true that it was due to the changes in the API, but that didn't work for me as well. I had to make another request like I wrote in my answer. Thanks anyways, I appreciate it. – Hasan Can Saral Aug 20 '15 at 23:05
3

Apparently you need to make another request like following (again in social pipeline):

def update_user_social_data(strategy, *args, **kwargs):
    if not kwargs['is_new']:
        return

    user = kwargs['user']

    fbuid = kwargs['response']['id']
    access_token = kwargs['response']['access_token']

    url = u'https://graph.facebook.com/{0}/' \
          u'?fields=email' \
          u'&access_token={1}'.format(
        fbuid,
        access_token,
    )

    request = urllib2.Request(url)
    email = json.loads(urllib2.urlopen(request).read()).get('email')

    user.email = email
    user.save()
Hasan Can Saral
  • 2,950
  • 5
  • 43
  • 78
  • 1
    this may not work all the time since email is not a mandatory field for having a Facebook account. For creating a Facebook account you need one but not necessarily both of email and mobile – Sagnik Sinha Jan 02 '16 at 09:36
  • 1
    It is possible that a user decides not to give away his/her email address on the permission access dialog, you can check kwargs['response']['granted_scopes'] and kwargs['response']['denied_scopes'] for references. To prompt user again for email, you can add SOCIAL_AUTH_FACEBOOK_AUTH_EXTRA_ARGUMENTS = {'auth_type': 'rerequest'} to settings.py. Ref: [Re-asking for Declined Permissions](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow) – Shihwei Jan 31 '17 at 10:54
-1

Facebook does not sends email-ids to localhost:8000. Check out the documentation here: python-django social auth for FB

Rishabh
  • 39
  • 7