0

I am using drf-social-oauth2 for social authentication in django. When I make a request to backend using following json

"grant_type": "convert_token",
"client_id": "QhT0Z....u3m5f",   
"client_secret":"W2DMVGg.....CfhO",
"backend":"google-oauth2",
"token": "ya29.a0Ael9sCNIcDes5Zb85GJCGWj9ok5kmCH8oBAWWJP9gGRu1Mzrqgtkw6Ut4WE-  aOaj0S5Fpf4IrZYjp8bYST93u6yb-MWIHzp3zmtUffbzKnA5VoKlvQ7aC5cSbCauBe4ckTn18XH0_3tWYn5QNg3D2bJqw6H1EAaCgYKARISARISFQF4udJhR0eV5UmE8pvApsrTCMq-8w0165"

then following response is returned

access_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbiI6IjVaU2tncnpJUlNIczlrd3liNUhrQXoyOFNwVVZnZCJ9.FRk7hYDP0ndlBpH3L2jkdNpO3kopRcLqCFfx-6C5GKA"
expires_in: 27791.630586
refresh_token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbiI6IjdibURRUk54ckdLbVJiczR5UGd0ZTJidVNPMklQRyJ9.r5wH-RqhzN2DaG5uUF4Z7F-8ufPgBTUPn7fWLVFwt3k"
scope: "read write"
token_type: "Bearer"

By default if this response is returned the user profile and email should automatically gets saved in the db but the drf-social-oauth2 is only returning the access tokens and is not saving user data.

So when I make request to fetch user, following error occurs

RelatedObjectDoesNotExist at /api/v1/user/
UserProfile has no student.

Following is my written code

settings.py

INSTALLED_APPS = [
    ...
    'oauth2_provider',
    'social_django',
    'drf_social_oauth2',
    'users',
    ...
]

AUTH_USER_MODEL = 'users.UserProfile'

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
        'drf_social_oauth2.authentication.SocialAuthentication',
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
}

AUTHENTICATION_BACKENDS = (
    # Google OAuth2
    'social_core.backends.google.GoogleOAuth2',
    # Facebook OAuth2
    'social_core.backends.facebook.FacebookAppOAuth2',
    'social_core.backends.facebook.FacebookOAuth2',
    # Instagram OAuth2
    'social_core.backends.instagram.InstagramOAuth2',
    # drf_social_oauth2
    'drf_social_oauth2.backends.DjangoOAuth2',
    # Django
    'django.contrib.auth.backends.ModelBackend',
)

ACTIVATE_JWT = True


SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.getenv("G_APP_ID")
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.getenv("G_APP_SECRET")

# Define SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE to get extra permissions from Google.
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile',
]

...

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                ...
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    },
]

urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('api/v1/auth/', include('drf_social_oauth2.urls', namespace='drf')),
    path('admin/', admin.site.urls),
    path('api/v1/', include('users.urls')),
]

managers.py

from typing import Optional
from django.contrib.auth.models import BaseUserManager, User

class UserProfileManager(BaseUserManager):
    def create_user(self, email: str, name: Optional[str] = None, password: Optional[str] = None) -> User:
        """Create a new user profile"""
        if not email:
            raise ValueError('User must have an email address')

        print("===================================", email)
        email = self.normalize_email(email)
        user = self.model(email=email, name=name)
        user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email: str, password: str, name: Optional[str] = None) -> User:
        """Create a new superuser profile"""
        user = self.create_user(email, name, password)
        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)

        return user

models.py

from .managers import UserProfileManager

class UserProfile(AbstractBaseUser, PermissionsMixin):
    name = models.CharField(max_length=100, null=True, blank=True)
    email = models.EmailField(unique=True)
    is_staff = models.BooleanField(default=False)
    print("I'm here")
    objects = UserProfileManager()

    USERNAME_FIELD = 'email'

    def __str__(self):
        return self.email


class Student(models.Model):
    user = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
    grade = models.CharField(max_length=100, null=True, blank=True)
    school = models.ForeignKey(School, on_delete=models.CASCADE, null=True, blank=True)
    phone = models.CharField(max_length=50, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'students'

    def __str__(self):
        return self.user.name

I've checked online, consulted chatGPT but nothing working. I expect the drf-social-oauth2 to save user profile and email while returning the tokens.

0 Answers0