Opened 5 years ago

Closed 5 years ago

#30471 closed Bug (duplicate)

"This account is inactive" error on login form will never display with ModelBackend

Reported by: Ben Owned by: nobody
Component: contrib.auth Version: 2.2
Severity: Normal Keywords: login is_active inactive message form
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In django/contrib/auth/forms.py the following code in clean tries to authenticate a username and password combination and show either an invalid login message (self.user_cache is None) or a message informing the user they are not allowed to login.

        if username is not None and password:
            self.user_cache = authenticate(self.request, username=username, password=password)
            if self.user_cache is None:
                raise self.get_invalid_login_error()
            else:
                self.confirm_login_allowed(self.user_cache)

        return self.cleaned_data

If the user has is_active set to false but provides the correct credentials I expect confirm_login_allowed to be called and eventually "This account is inactive" to be returned as an error.

However, this is not happening because in django/contrib/auth/backends.py we have:

    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

The user_can_authenticate check checks for is_active so regardless of the success/failure of the login if is_active is false then user_can_authenticate will always return None.

I suspect the fix here is to remove the confirm_login_allowed check or use User.check_password after the failed authentication to drive the inactive logic. I am not sure which way the project would prefer to go and since this is important code I thought it best to ask. I'm happy to roll a patch once there's consensus on a good fix.

Change History (2)

comment:1 by Ben, 5 years ago

Component: Uncategorizedcontrib.auth

comment:2 by Tim Graham, 5 years ago

Resolution: duplicate
Status: newclosed

Duplicate of #28645.

Note: See TracTickets for help on using tickets.
Back to Top