Unable to authenticate correctly with custom django authentication backend

35 Views Asked by At

I have a custom authentication backend that should authenticate tutors as they login. The issue is that the authentication backend returns a user object with correct credentials, but the @login_required decorator receives None for request.user.is_authenticated. So the loop goes from login to login endlessly. I tried printing the session_key across requests, and it is the same.

FILES

Authentication Backend

class TutorAuthBackend(ModelBackend):
    def authenticate(self, request, username_or_email=None, password=None, **kwargs):
        print(f"Attempting to authenticate: {username_or_email}")
        try:
            validate_email(username_or_email)
            is_valid_email_format = True
        except ValidationError:
            is_valid_email_format = False

        auth_type = 'email__iexact' if is_valid_email_format else 'username__iexact'
        auth_param = {auth_type: username_or_email}

        try:
            tutor = Tutor.objects.get(**auth_param)
            if tutor.check_password(password):
                print(f"Authenticated: {tutor}")
                return tutor
        except Tutor.DoesNotExist:
            pass

        return None

    def get_user(self, user_id):
        """
        Returns the tutor object using the given user_id.
        """
        try:
            return Tutor.objects.get(pk=user_id)
        except Tutor.DoesNotExist:
            return None


def tutor_login(request):
    if request.method == 'POST':
        username_or_email = request.POST.get('username_or_email')
        password = request.POST.get('password')
        tutor = TutorAuthBackend().authenticate(request, username_or_email=username_or_email, password=password)
        if tutor:
            login(request, tutor, backend='tutor.backends.TutorAuthBackend')
            messages.success(request, "You're Logged In")
            if tutor.profile_picture:
                print("Profile Picture:", tutor.profile_picture.url)
                return redirect('tutor_dashboard', tutor_id=tutor.id)
            return redirect('tutor_profile')
        else:
            tutor_exists = Tutor.objects.filter(username=username_or_email).exists()
            if tutor_exists:
                messages.error(request, 'Incorrect Password')
            else:
                messages.error(request, 'User Not Found')
            return render(request, 'tutor/tutor_login.html', context={'username_or_email': username_or_email})
    else:
        return render(request, 'tutor/tutor_login.html')

First, I tried to print out how the view communicates with the authentication backend by printing before and after the backend returns something. The backend returns a valid authenticated user. In the dashboard view, I printed request.user.is_authenticated() and it returns false, I printed the request.user and it returned AnonymousUser. I tried to know if the session was the problem by increasing the SESSION_COOKIE_AGE to 7 days and explicitly specifying the SESSION_ENGINE to django.contrib.sessions.backends.db in settings.py. I have also tried to log the session_key for each user looping the login page, and it appears consistent. I couldn't make helpful meaning from the Django docs too. Thank you in advance for your assistance.

1

There are 1 best solutions below

0
On BEST ANSWER

I have resolved the issue. The problem was of naming convention. My custom backend was named tutor_backends.py rather than backends.py.It seems Django doesn't understand any custom backend that is not exactly named backends.py. So even though the logic is correct and the backend authenticates, the authentication does not persist to session hence, @login_required which checks is a session user is_authenticated receives an False beccause auths doesn't persist to session. I hope this helps someone. Unfortunately, I didn't see that spelt out in the docs.