Mojtaba
Mojtaba

Reputation: 593

Save a field as hash and compare it in django

I created my own user model:

class CustomUser(AbstractBaseUser,PermissionsMixin):
    phone_number = models.CharField(verbose_name="Mobile Number", max_length=11, unique=True, blank=False, null=False)
    security_code = models.IntegerField(verbose_name="Security Code",default=create_security_code)
    security_code_creation = models.DateTimeField(auto_now=True)

a user can login with password or security code.

I want it to be like this:

If user wants to login with security code I will create a random security code in my view. text it to them and save the hashed version of the security code in my database. user enters the number from text they received and I compare the hashed version of what user entered with what I have in my database. much like a password.

but I don't want to store security code as plain text in my database. I want to store it like password (hashed).

I found

from django.contrib.auth.hashers import make_password

which I can use to create a hashed version of security code.

my question is should I write a separate authentication backend or simply write/use a function like check_password that is implanted in AbstractBaseUser?

Upvotes: 0

Views: 1356

Answers (1)

Iain Shelvington
Iain Shelvington

Reputation: 32244

Overriding check_password in your custom user class could work something like this.

You provide a password or a code when logging in and the method first checks if the value matches the password and if not then it checks if the value matches the security code

from django.contrib.auth.hashers import check_password, make_password

class CustomUser(AbstractBaseUser, PermissionsMixin):
    ...
    security_code = models.CharField(verbose_name="Security Code",max_length=128)
    ...
    def set_security_code(self, code):
        self.security_code = make_password(code)
        self.security_code_creation = now()

    def check_password(self, raw_password):
        password_matched = super().check_password(raw_password)
        if not password_matched and self.security_code_creation > now() - timedelta(days=1):
            return check_password(raw_password, self.security_code)
        return False

Upvotes: 3

Related Questions