django-oauth2-provider with custom user model?

3.5k Views Asked by At

I am really stuck in my project right now. I am trying to implement Oauth2 for my app. I found out about django-oauth2-provider a lot and tried it. The only problem is, it uses the User model at django.contrib.auth. The main users of our site are saved in a custom model called User which does not inherit from or extend the model at django.contrib.auth.

Is there any way to use my custom User model for creating clients and token?

If django-oauth2-provider can't be used for this purpose, can anyone recommend me some oauth2 library with the option to implement oauth2 with my own model.

Sincerely,

Sushant Karki

4

There are 4 best solutions below

0
On

As the previous answer suggested, you should extend AbstractUser from django.contrib.auth.models.

The problem with the access token that the OP referring to, occur when changing the setting AUTH_USER_MODEL AFTER django-oauth2-provider was migrated.

When django-oauth2-provider is migrated, it creates a key constrain between the User model and django-oauth2-provider.

The solution is very easy:

  1. Create your new User model and change the AUTH_USER_MODEL setting.
  2. Go to the django_migration table in your database.
  3. Delete all rows of django-oauth2-provider.
  4. run python manage.py makemigrations
  5. run python manage.py migrate

Now, the django-oauth2-provider tables are connected to the RIGHT User model.

1
On

django-oauth2-provider fetches the user model using settings.AUTH_USER_MODEL, with a fallback to auth.User. If you extend AbstractUser your User model will include all the fields of auth.User plus any additional fields you specify.

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    some_additional_field = models.BooleanField(default=False)

Specify the user model to be used like this in settings.py:

AUTH_USER_MODEL = 'user_api.User'

If you don't want to base your user on AbstractUser you'll also need to write your own user manager, e.g. by extending the BaseUserManager

You can read more about ways to customize django's user model here.

0
On

bro, I faced the same problem I am clear about them exactly how to do a custom user model with Oauth2.

now I use SimpleJWT for the authentication

you can check this documentation it will help to solve your problem click here

0
On

You have to create a custom OAuth2Validator and override the validate_user function.

"""API Core Auth Utils"""

from django.core.exceptions import ObjectDoesNotExist
from oauth2_provider.oauth2_validators import OAuth2Validator
from rest_framework.request import Request

from core.models import Customer
from core.models.serializers import UserSerializer


class OAuthValidator(OAuth2Validator):  # pylint: disable=abstract-method
    """Custom Validator to be used with OIDC"""

    def get_userinfo_claims(self, request):
        claims = super().get_userinfo_claims(request)
        ...
        return claims

    def get_additional_claims(self, request: Request):
        return {
            "id": request.user.id,
            "email": request.user.email,
            "username": request.user.username,
            "given_name": request.user.first_name,
            "family_name": request.user.last_name,
            "name": f"{request.user.first_name} {request.user.last_name}",
        }


class OAuthCustomerValidator(OAuth2Validator):  # pylint: disable=abstract-method
    """Custom OAuth Validator for Customers to be used with OIDC"""

    def validate_user(self, username, password, client, request, *args, **kwargs):
        try:
            customer = Customer.objects.get(email=username)
            if customer.is_active and customer.authenticate(password):
                request.user = customer
                return True
            return False
        except ObjectDoesNotExist:
            return False

Also, you can implement the RequestValidator: from oauthlib.openid import RequestValidator