Getting phone number of user in a django app from google with social_core
Hello I am working on a Django app that have Customuser model and i just save users phone number in the model for some reasons this is my model and manager :
class CustomUserManager(BaseUserManager):
def create_user(self, phone_number, password=None, **extra_fields):
if not phone_number:
raise ValueError('The Phone Number must be set')
user = self.model(phone_number=phone_number, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, phone_number, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(phone_number, password, **extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
phone_number = models.CharField(max_length=15, unique=True)
email = models.EmailField(unique=True, null=True, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
score = models.PositiveIntegerField(default=10, null=True, blank=True)
objects = CustomUserManager()
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELDS = []
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
Profile.objects.get_or_create(user=self)
def add_score(self, score):
self.score += score
print(self.score)
self.save()
def decrease_score(self, score):
self.score -= score
self.save()
def generate_referral_code(self):
code_length = 19
characters = string.ascii_letters + string.digits
unique_code = ''.join(random.choice(characters) for _ in range(code_length))
while ReferralCode.objects.filter(code=unique_code).exists():
unique_code = ''.join(random.choice(characters) for _ in range(code_length))
ReferralCode.objects.create(user=self, code=unique_code)
def get_referral_code(self):
try:
return self.referralcode.code
except ReferralCode.DoesNotExist:
return None
def __str__(self):
return self.phone_number
i edit my setting.py file for having a pipleline file like this :
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = config("GOOGLE_CLIENT_ID")
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = config("GOOGLE_SECRET")
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/user.phonenumbers.read',
]
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',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'accounts.pipeline.save_profile',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)
and in pipeline.py i expect to get user phone number to save in database but i get None also in Json file i dont see any information about user phone neumber how can i get the mobile phone ? thank you
from .models import Profile
import json
def save_profile(backend, user, response, *args, **kwargs):
if backend.name == 'google-oauth2':
print(json.dumps(response, indent=2))
phone_number = response.get('phoneNumber')
print(f"this is phone number{phone_number}")
if phone_number:
user.phone_number = phone_number
user.email = response.get('email')
user.first_name = response.get('given_name')
user.last_name = response.get('family_name')
user.save()
Profile.objects.get_or_create(
user=user,
defaults={
'email': response.get('email'),
'first_name': response.get('given_name', ''),
'last_name': response.get('family_name', '')
}
)
google doesn't automatically include phone numbers in the response. This is because the phone number is classified as sensitive data and requires explicit user permission, often handled separately.
To get the user's phone number using Google OAuth, you need to use a different Google API endpoint or a separate request to retrieve it after the initial OAuth authentication.
here's how you can do it.
....
if backend.name == 'google-oauth2':
# Print the OAuth2 response
print(json.dumps(response, indent=2))
# Access the user's profile using the People API
access_token = response.get('access_token')
if access_token:
people_api_url = "https://people.googleapis.com/v1/people/me?personFields=phoneNumbers"
headers = {
"Authorization": f"Bearer {access_token}"
}
people_response = requests.get(people_api_url, headers=headers)
people_data = people_response.json()
# Extract the phone number from the People API response
phone_number = None
phone_numbers = people_data.get('phoneNumbers')
if phone_numbers:
phone_number = phone_numbers[0].get('value') # First phone number
print(f"this is phone number: {phone_number}")
if phone_number:
user.phone_number = phone_number
# Set other profile fields
....