Django custom password not getting hash for custom users

I am currently performing authentication for a Django app I am writing. Following the code of the Thinkster Django course, I went through the entire registration process, but I cannot login because the password is not hashed when the user logs in.

Here is my custom user model and function create_user

.

class UserManager(BaseUserManager)
    def create_user(self, username, email, password=None):

        if username is None:
            raise TypeError('Users must have a username.')

        if email is None:
            raise TypeError('Users must have an email address.')

        user = self.model(username=username, email=self.normalize_email(email))
        user.set_password(password)
        user.save()

        return user

    def create_superuse(self, username, email, password):
        if password is None:
            raise TypeError('Superusers must have a password.')

        user = self.create_user(username, email, password)
        user.is_superuser = True
        user.is_staff = True
        user.save()

        return user

class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(db_index=True, max_length=255, unique=True)
    email = models.EmailField(db_index=True, unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = UserManager()

      

As you can see, I am explicitly calling the function set_password

, but I cannot find out why it is not being executed correctly.

Mine Serializer

where I create user looks like this:

class RegistrationSerializer(serializers.ModelSerializer):

    password = serializers.CharField(
        max_length=128,
        min_length=8,
        write_only=True
    )

token = serializers.CharField(max_length=255, read_only=True)

class Meta:
    model = User
    fields = ['email', 'username', 'password', 'token']

    def create(self, validated_data):
        return User.objects.create_user(**validated_data)

      

Note that instead return User.objects.create_user(**validated_data)

I also tried to do return get_user_model().objects.create_user(**validated_data)

as it was a suggestion on a different question, but that didn't work either.

I also post my opinion in case there is something wrong, but I really don't think this is the case.

class RegistrationAPIView(APIView):
    permission_classes = (AllowAny,)
    renderer_classes = (UserJSONRenderer,)
    serializer_class = RegistrationSerializer

    def post(self, request):
        user = request.data.get('user', {})

        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)

      

Side note . If this is relevant, I post requests since Postman

and all the responses I receive seem to be perfectly correct. But when I go through my SQLite I see that the password has not been hashed. This also results in users being unable to log in because during the login process the password is hashed and then compared to the one in the database.

Side note 2 . When I log in a user through the command line with python manage.py createsuperuser

, he gets a hashed password and everything works as I usually expect.

+3


source to share


3 answers


In the comment above, make_password

I want to add the following to the method create_user

:



from django.contrib.auth.hashers import make_password


def create_user(self, username, email, password=None):

    if username is None:
        raise TypeError('Users must have a username.')

    if email is None:
        raise TypeError('Users must have an email address.')

    user = User.objects.create(
       email=email,
       username=username,
       password = make_password(password))

    return user

      

+2


source


You need to use set_password method like this in serializer:



def create(self, validated_data):
        user = User(email=validated_data['email'], username=validated_data['username'])
        user.set_password(validated_data['password'])
        user.save()
        return user

      

+1


source


I think Surajano is on to something. I don't know if this will help solve your problem, but I ran into the same problem a while ago with creating a superuser not hashing the password.

How I solved it:

def create_superuser(self, email, first_name, last_name, password):
    user = self.create_user(
        email,
        first_name,
        last_name,
        password=password,
    )

      

you need to explicitly provide password = password

Also, I see a typo in your def create_superuser (you have that def create_superuse), which might cause some problems later.

Anyway, I posted a question about this and a solution, you can check it out here:

UserCreateForm bypassing UserManager, normal users created with UserCreateForm CAN authenticate, but superuser created in CAN shell NOT?

Again, I don't know if this helps you or not, but hopefully it gives you an idea of ​​how to at least deduce the solution. My example doesn't use token-based authentication - so no serializer - but I don't think it matters as they are probably not related.

0


source







All Articles