Search code examples
django-rest-frameworkdjango-rest-framework-simplejwt

djangorestframework-simplejwt getting "No active account found with the given credentials" although I know my user exists


I'm fairly new to Django and feel I must be missing something. I have an application where I want two user types (UserType1 and UserType2). I am using the base user model with boolean flags and then created OneToOne fields on these objects to the user (no extra data added at this point).

This gives me the following user models:

from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.core.exceptions import ValidationError
from django.db import models
from django_extensions.db.models import TimeStampedModel


class User(AbstractUser):
    """
    Default user model for the platform
    """
    email = models.EmailField()
    is_user_type_1 = models.BooleanField(default=False)
    is_user_type_2 = models.BooleanField(default=False)

    # Use default UserManager for now
    objects = UserManager()


class UserType1(TimeStampedModel):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name='user_type1',
    )


class UserType2(TimeStampedModel):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name='user_type2'
    )

I then wrote serializes for these classes where I only want to expose and endpoint for UserType1 and UserType2 (rather than User itself). This should allow the users to create an instance of UserType1 or UserType2 which will also create the row in the User table (although maybe not super important for this). Here are the serializers:

from django.db import transaction
from rest_framework import serializers

from .models import User, UserType1, UserType2


class UserSerializer(serializers.ModelSerializer):
    """
    Serializer for the `User` model
    """

    class Meta:
        model = User
        fields = (
            'username',
            'email',
            'password',
            'first_name',
            'last_name',
            'is_active',
        )
        extra_kwargs = {'password': {'write_only': True}}


class UserType1Serializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    class Meta:
        model = UserType1
        fields = (
            'user',
            'created',
            'modified',
        )

    @transaction.atomic
    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user_data.is_user_type_1 = True
        user_data.is_user_type_2 = False
        user = UserSerializer.create(UserSerializer(), validated_data=user_data)

        user_type_1, created = UserType1.objects.update_or_create(
            user=user,
        )

        return user_type_1

class UserType2Serializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    class Meta:
        model = UserType2
        fields = (
            'user',
            'created',
            'modified',
        )

    @transaction.atomic
    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user_data.is_user_type_1 = False
        user_data.is_user_type_2 = True
        user = UserSerializer.create(UserSerializer(), validated_data=user_data)

        user_type2, created = UserType2.objects.update_or_create(
            user=user,
        )

        return user_type2

The User model was registered in my settings:

AUTH_USER_MODEL = 'user.User'

After I create a superuser, I am successfully able to get my tokens and use them to access other views:

{
    "refresh": "xxxx",
    "access": "xxxx"
}

However, if I create a user from admin (or I have fixtures that create users and user_type1/user_type2 objects), every time I try to get the tokens I am getting:

{
    "detail": "No active account found with the given credentials"
}

but I know they exist in the DB since I can see them properly in the admin console. I thought this was something to do with hashing of the password but was unable to solve it.

This also contains the following admin.py file:

from django.contrib import admin

from .models import User, UserType1, UserType2

admin.site.register(User)
admin.site.register(UserType1)
admin.site.register(UserType2)

Any help would be greatly appreciated!!


Solution

  • Register your custom User model in the admin with:

    from django.contrib.auth.admin import UserAdmin
    
    admin.site.register(models.User, UserAdmin)
    

    Or follow the documentation on how to register a custom User model in admin. A full example

    create a new User via admin panel and check if the password is hashed. Then make the api call to your jwt endpoint again.