question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

e-mail as username when using facebook not working

See original GitHub issue

I have set SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True in my settings, but still username for users registering via facebook have username FirstnameLastname. What should Ido to make the setting work?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

21reactions
aminehaddadcommented, Jan 30, 2017

@ivellios, @omab, there are a few issues with using just email address as the main account:

  1. if a user already exists with that email address and database has emails as unique, then social-auth will generate an invalid email address for the user.
  2. If user does not provide email over social networks (permissions, etc.), it will use FirstNameLastName (username) which is NOT correct if you depend on username being the email address.
  3. If user creates social email account and/or regular email account, email sensitivity matters and user is forced to login using UPPERlowerCaSe@email.com (which is normal for email standards but not for users to remember which letters were upper/lower case).
  4. Custom case if email is username: If user is already logged in as socialA@facebook.com, and logs in as socialA@gmail.com, then accounts should NOT be linked (validate both emails).

To solve these problems, I created a custom get_username pipeline:

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
import urllib

# This is initially from https://github.com/python-social-auth/social-core/blob/master/social_core/pipeline/user.py
def get_username(strategy, details, backend, user=None, *args, **kwargs):
    # Get the logged in user (if any)
    logged_in_user = strategy.storage.user.get_username(user)

    # Custom: check for email being provided
    if not details.get('email'):
        error = "Sorry, but your social network (Facebook or Google) needs to provide us your email address."
        return HttpResponseRedirect(reverse('repairs-social-network-error') + "?error=" + urllib.quote_plus(error))

    # Custom: if user is already logged in, double check his email matches the social network email
    if logged_in_user:
        if logged_in_user.lower() != details.get('email').lower():
            error = "Sorry, but you are already logged in with another account, and the email addresses do not match. Try logging out first, please."
            return HttpResponseRedirect(reverse('repairs-social-network-error') + "?error=" + urllib.quote_plus(error))

    return {
        'username': details.get('email').lower(),
    }

In settings:

INSTALLED_APPS += [
    'social_django',
]

# User models
AUTH_USER_MODEL = 'repairs_accounts.MyUser'
SOCIAL_AUTH_USER_MODEL = 'repairs_accounts.MyUser'

# Allowed authentication backends (social + django)
AUTHENTICATION_BACKENDS = [
    # Social logins
    'social_core.backends.facebook.FacebookOAuth2',
    'social_core.backends.google.GoogleOAuth2',

    # Default django login
    'django.contrib.auth.backends.ModelBackend',
]

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'social_core.pipeline.social_auth.social_user',

    # Make up a username for this person, appends a random string at the end if
    # there's any collision.
    # 'social_core.pipeline.user.get_username',

    # CUSTOM: this gets email address as the username and validates it matches
    # the logged in user's email address.
    'repairs_accounts.pipeline.get_username',

    # 'social_core.pipeline.mail.mail_validation',
    'social_core.pipeline.social_auth.associate_by_email',
    'social_core.pipeline.user.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details'
)

# Facebook settings
SOCIAL_AUTH_FACEBOOK_KEY = '..'
SOCIAL_AUTH_FACEBOOK_SECRET = '..'

SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
    'fields': 'id, name, email, age_range',
}
SOCIAL_AUTH_FACEBOOK_AUTH_EXTRA_ARGUMENTS = {
    # 'auth_type': 'reauthenticate',
}

# Google settings
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '..'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '..'
SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {
      # 'access_type': 'offline',
      # 'approval_prompt': 'force',
}

If you have a custom User (BaseUserManager) that only takes email address, you need to let social-auth pass the field ‘username’ or else it will crash:

class MyUserManager(BaseUserManager):
    def create_user(self, email, password=None, username=""):
        """
        Creates and saves a User with the given email and password.

        NOTE: Argument 'username' is needed for social-auth. It is not actually used.
        """
        if not email:
            raise ValueError('Users must have an email address.')

        # Validate email is unique in database
        if MyUser.objects.filter(email = self.normalize_email(email).lower()).exists():
            raise ValueError('This email has already been registered.')

        user = self.model(
            email=self.normalize_email(email).lower(),
        )

        user.set_password(password)

        # Save and catch IntegrityError (due to email being unique)
        try:
            user.save(using=self._db)

        except IntegrityError:
            raise ValueError('This email has already been registered.')

        return user

class MyUser(AbstractBaseUser):
    objects = MyUserManager()

    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
        error_messages={
            'unique':"This email has already been registered.",
        }
    )

    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    # Custom: was this email validated, at some point, by sending an email?
    is_email_validated = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

It takes a while to solve this (plus handling email/password registrations without social networks) but it ends up working great.

6reactions
lsandoval0000commented, Dec 24, 2018

I got the same problem but, just adding SOCIAL_AUTH_FACEBOOK_SCOPE = ['email'] SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'fields': 'id, name, email, age_range', } solved my problem ✌️

Read more comments on GitHub >

github_iconTop Results From Across the Web

Possible issues creating a Facebook account with your email
There are a few reasons you may be having trouble creating a Facebook account with your email address. If you follow these steps...
Read more >
Email Already in Use - Facebook
If there's already a Facebook account associated with your email or phone number and you don't own that account, please use this form...
Read more >
Recover Your Facebook Account if You Can't Log In.
1. Go to the Find Your Account page at facebook.com/login/identify and follow the instructions. · 2. Search for the account you want to...
Read more >
Add or remove an email from your Facebook account
1. Tap in the top right of Facebook. ; 2. Scroll down and tap Settings. ; 3. In the Account Settings section, tap...
Read more >
I used the wrong email to create my Facebook account. How ...
1. Make sure that you have a secure email that only you can access. ; 2. Go to facebook.com/confirmemail.php. ; 3. Enter your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found