Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How not to set the user's email address in django social-auth

I have django social-auth installed (from omab) and the users have an email address in database that is the one I want to keep but when the users log in from facebook using social-auth, their email gets replaced by the one they have in their facebook account. I am not sure the settings are the one by default or not and cannot find how to stop this behavior.

like image 810
Bastian Avatar asked Mar 26 '12 22:03

Bastian


3 Answers

Have you tried SOCIAL_AUTH_PROTECTED_USER_FIELDS? :)

From the manual:

The update_user_details pipeline processor will set certain fields on user objects, such as email. Set this to a list of fields you only want to set for newly created users:

SOCIAL_AUTH_PROTECTED_USER_FIELDS = ['email',]

Also more extra values will be stored if defined. Details about this setting are listed below in the OpenId and OAuth sections.

like image 152
Zhe Li Avatar answered Nov 13 '22 07:11

Zhe Li


I found it, in the pipeline the responsible for that is

social_auth.backends.pipeline.user.update_user_details

I just removed it from the pipeline and now the details like email address and name are left to the user to fill.

like image 5
Bastian Avatar answered Nov 13 '22 06:11

Bastian


I'm posting my solution (update user details, not overwrite them) so it may help someone. Based on pipeline.user.update_user_details I coded the following:

def fill_user_details(backend, details, response, user, is_new=False, *args,
                        **kwargs):
    """Fills user details using data from provider, without overwriting
    existing values.

    backend: Current social authentication backend
    details: User details given by authentication provider
    response: ?
    user: User ID given by authentication provider
    is_new: flag

    source: social_auth.backends.pipeline.user.update_user_details
    """
    # Each pipeline entry must return a dict or None, any value in the dict
    # will be used in the kwargs argument for the next pipeline entry.
    #
    # If any function returns something else beside a dict or None, the
    # workflow will be cut and the value returned immediately, this is useful
    # to return HttpReponse instances like HttpResponseRedirect.

    changed = False  # flag to track changes

    for name, value in details.iteritems():
        # do not update username, it was already generated
        if name in (USERNAME, 'id', 'pk'):
            continue

        # set it only if the existing value is not set or is an empty string
        existing_value = getattr(user, name, None)
        if value is not None and (existing_value is None or
                                  not is_valid_string(existing_value)):
            setattr(user, name, value)
            changed = True

    # Fire a pre-update signal sending current backend instance,
    # user instance (created or retrieved from database), service
    # response and processed details.
    #
    # Also fire socialauth_registered signal for newly registered
    # users.
    #
    # Signal handlers must return True or False to signal instance
    # changes. Send method returns a list of tuples with receiver
    # and it's response.
    signal_response = lambda (receiver, response): response
    signal_kwargs = {'sender': backend.__class__, 'user': user,
                     'response': response, 'details': details}

    changed |= any(filter(signal_response, pre_update.send(**signal_kwargs)))

    # Fire socialauth_registered signal on new user registration
    if is_new:
        changed |= any(filter(signal_response,
            socialauth_registered.send(**signal_kwargs)))

    if changed:
        user.save()
like image 3
glarrain Avatar answered Nov 13 '22 07:11

glarrain