When trying to authenticate a user created through a view in DRF Browsable API, I get
No active account found with the given credentials
The view:
class MyUserCreate(APIView):
def post(self, request, format='json'):
serializer = MyUserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
The serializer:
class MyUserSerializer(serializers.ModelSerializer):
username = serializers.CharField(
required=True,
validators=[UniqueValidator(queryset=MyUser.objects.all())],
min_length=5,
max_length=20
),
password = serializers.CharField(
required=True,
max_length=256
)
class Meta:
model = MyUser
fields = ('username', 'password')
def create(self, validated_data):
password = make_password(validated_data['password'])
user = MyUser.objects.create_user(validated_data['username'], password)
return user
The password is being hashed. At this stage, went on to the admin page and tested to login there too with the created account and got
Made sure the custom user model had is_active, is_superuser and is_staff and checked if that would fix the issue but it didn't.
class MyUserManager(BaseUserManager):
def create_user(self, username, password, **extra_fields):
user = self.model(
username=username
)
user.is_staff=True
user.is_active=True
user.is_superuser=True
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(username, password, **extra_fields)
class MyUser(AbstractBaseUser):
objects = MyUserManager()
class Meta:
# managed = False
db_table = 'user_entity'
user_id = models.AutoField(primary_key=True, db_column='userId')
username = models.CharField(db_column='username', unique=True, max_length=20)
password = models.CharField(db_column='userPassword', max_length=256)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=True)
USERNAME_FIELD = 'username'
def __str__(self):
return str(self.user_id) + " (%s)" % str(self.username)
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
Then, tried to create the user using python manage.py createsuperuser
... doing so then I'm able to both login in the admin pannel and authenticate that user with the Token Obtain Pair view shown initially.
First of all. Thank you for providing all the details. It is always easier to debug. Coming to the issue, the problem is that you are using make_password
explicitly.
If you would look through the Django's set_password
documentation, you'd find that it takes care of hashing.
What you are doing is, first you are hashing your password, and providing it as a raw value to set_password
method via create_user
. The set_password
would assume that as a raw value and would hash it again. Hence, your original password is not used at all.
You can just remove the use of make_password
and instead change your serializer's create
method to
class MyUserSerializer(serializers.ModelSerializer):
...
def create(self, validated_data):
user = MyUser.objects.create_user(validated_data['username'], validated_data["password"])
return user
This should resolve your query. I hope it helps! :)