diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 2c038e8111..18fca67439 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -192,6 +192,15 @@ class AuthenticationForm(forms.Form): if username is not None and password: self.user_cache = authenticate(self.request, username=username, password=password) if self.user_cache is None: + # An authentication backend may reject inactive users. Check + # if the user exists and is inactive, and raise the 'inactive' + # error if so. + try: + self.user_cache = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + pass + else: + self.confirm_login_allowed(self.user_cache) raise self.get_invalid_login_error() else: self.confirm_login_allowed(self.user_cache) diff --git a/docs/releases/1.11.8.txt b/docs/releases/1.11.8.txt index dd9d19ae19..dd9fb0c3ce 100644 --- a/docs/releases/1.11.8.txt +++ b/docs/releases/1.11.8.txt @@ -9,4 +9,5 @@ Django 1.11.8 fixes several bugs in 1.11.7. Bugfixes ======== -* ... +* Reallowed, following a regression in Django 1.10, ``AuthenticationForm`` to + raise the inactive user error when using ``ModelBackend`` (:ticket:`28645`). diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py index 1832f81c1c..5d2074e33a 100644 --- a/tests/auth_tests/test_forms.py +++ b/tests/auth_tests/test_forms.py @@ -262,9 +262,6 @@ class UserCreationFormTest(TestDataMixin, TestCase): ) -# To verify that the login form rejects inactive users, use an authentication -# backend that allows them. -@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend']) class AuthenticationFormTest(TestDataMixin, TestCase): def test_invalid_username(self): @@ -323,6 +320,8 @@ class AuthenticationFormTest(TestDataMixin, TestCase): self.assertFalse(form.is_valid()) self.assertEqual(form.non_field_errors(), [str(form.error_messages['inactive'])]) + # Use an authentication backend that allows inactive users. + @override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend']) def test_custom_login_allowed_policy(self): # The user is inactive, but our custom form policy allows them to log in. data = {