Prashant Singh
Prashant Singh

Reputation: 536

AbstractUser in Django is not authenticating

Django version 3.2

I have created a AbstractUser model for storing info of Bank's Customer . I am able to register the customer with username and password . But it's not getting authenticated while login . In admin page the password is saved as plain text , which is not expected . It should be saved in hashed form by default in Django . Please give some directions to solve this . What I am doing wrong ?

In settings.py I have added line : AUTH_USER_MODEL = 'banking.Customer'

models.py :

'''
    This stores all customers of this bank .
'''
class Customer(AbstractUser):
    #username   = models.CharField(max_length=128, unique=True)
    #first_name     = models.CharField(max_length=128)
    #last_name  = models.CharField(max_length=128)
    #email      = models.CharField(max_length=128)
    phone       = models.CharField(max_length=128)
    #password   = models.CharField(max_length=2048)
    dateJoined = models.DateTimeField(auto_now_add=True)

    # completed, pending, blocked, error
    verificationStatus = models.CharField(max_length=128)

    #USERNAME_FIELD = 'username'
    #REQUIRED_FIELDS = []

    def __str__(self):
        return f"{self.username}, {self.first_name} {self.last_name}, {self.email}, {self.password}"

views.py :

def register(request):
    if request.method == "POST":
        
        # get the information from form
        print("POST request :" + str(request.POST))
        userName = request.POST["userName"]
        firstName = request.POST["firstName"]
        lastName = request.POST["lastName"]
        email = request.POST["email"]
        phone = request.POST["phone"]
        password = request.POST["password"]

        # insert it in DB, keep in mind that username should be unique
        try:
            customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")
            customer.save()

            print("Database " + str(customer))
            return HttpResponseRedirect(reverse('login'))
        except:
            # send register page agin with error message
            context = {"message": userName + " userName is already taken ."}
            return render(request, "banking/register.html", context)
    else:
        return render(request, "banking/register.html")



def login(request):
    if request.method == "POST":
        # get info from login form
        username = request.POST["userName"]
        password = request.POST["password"]

        # check if user is valid
        customer = None
        try:
            # check if userName exist in DB
            print("check user")
            customer = authenticate(request, username=username, password=password)
        except:
            customer = None
        
        # save customer in session
        if customer is not None:
            login(request, customer)
            return HttpResponseRedirect(reverse('mainPage'))
        else:
            # return to login page with error message
            context = {"message": "Invalid credentials"}
            return render(request, "banking/login.html", context) 
    else:
        return render(request, "banking/login.html")

Upvotes: 1

Views: 1177

Answers (3)

Astik Gabani
Astik Gabani

Reputation: 605

When creating the custom User class in Django, password encryption and saving mechanism should be handled by the Manager class.
See the code used from the EmployeeManager class in the astikgabani/Inventory-Management repository.

Upvotes: 0

Aadarsha
Aadarsha

Reputation: 186

In your register() method of views.py, you have to edit your code to be:

customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, verificationStatus="verified")
customer.set_password(password)
customer.save()

While saving user, we have to set passwords using set_password() method, as it will save password using appropriate hash/encryption algorithm.

Upvotes: 2

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21807

You create the customer by using the models __init__ method (the constructor):

customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")

But this does not consider the fact that the password needs to be hashed and saves the password as plain text. This causes your user to be unable to login as the authenticate function works on the premise that the password is hashed.

You should instead use the create_user [Django docs] method of the user model's manager, UserManager, which will automatically hash the password:

customer = Customer.objects.create_user(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")

Upvotes: 0

Related Questions