﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
30471	"""This account is inactive"" error on login form will never display with ModelBackend"	Ben	nobody	"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."	Bug	closed	contrib.auth	2.2	Normal	duplicate	login is_active inactive message form		Unreviewed	0	0	0	0	0	0
