diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
index 6b31f72..4ee326b 100644
--- a/django/contrib/auth/backends.py
+++ b/django/contrib/auth/backends.py
@@ -10,6 +10,9 @@ class ModelBackend(object):
 
     def authenticate(self, username=None, password=None, **kwargs):
         UserModel = get_user_model()
+
+        user = UserModel()
+
         if username is None:
             username = kwargs.get(UserModel.USERNAME_FIELD)
         try:
@@ -17,6 +20,11 @@ class ModelBackend(object):
             if user.check_password(password):
                 return user
         except UserModel.DoesNotExist:
+            #This call to set password is used to force the hasher to run.
+            #It helps to even out the timing between a successful and
+            #unsuccessful authentication attempt, helping to mitigate a timing
+            #vuln.
+            user.set_password(password)
             return None
 
     def get_group_permissions(self, user_obj, obj=None):
diff --git a/django/contrib/auth/tests/test_auth_backends.py b/django/contrib/auth/tests/test_auth_backends.py
index fc5a80e..aa69220 100644
--- a/django/contrib/auth/tests/test_auth_backends.py
+++ b/django/contrib/auth/tests/test_auth_backends.py
@@ -12,7 +12,22 @@ from django.contrib.auth import authenticate, get_user
 from django.http import HttpRequest
 from django.test import TestCase
 from django.test.utils import override_settings
+from django.contrib.auth.hashers import MD5PasswordHasher
 
+"""
+Mock hasher which counts number of times hashes are computed
+
+Used in test_authentication_timing
+
+Refs #20760
+"""
+class MockHasher(MD5PasswordHasher):
+    def __init__(self):
+        MockHasher.hash_count = 0
+
+    def encode(self, password, salt, iterations=None):
+        MockHasher.hash_count = MockHasher.hash_count + 1
+        return super(MockHasher, self).encode(password, salt, iterations)
 
 class BaseModelBackendTest(object):
     """
@@ -111,6 +126,26 @@ class BaseModelBackendTest(object):
         user = self.UserModel._default_manager.get(pk=self.superuser.pk)
         self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))
 
+    @override_settings(PASSWORD_HASHERS=('django.contrib.auth.tests.test_auth_backends.MockHasher',))
+    def test_authentication_timing(self):
+        """
+        Tests that the hasher is run the same number of times whether a user exists or not
+
+        Refs #20760
+        """
+        #ensures the proper natural key is passed in custom models
+        kwargs = {self.UserModel.USERNAME_FIELD : self.UserModel._default_manager.get(pk=1).natural_key()[0]}
+        authenticate(password='test', **kwargs)
+        exists = MockHasher.hash_count
+
+        MockHasher.hash_count = 0
+
+        #don't use these creds in a test account
+        kwargs = {self.UserModel.USERNAME_FIELD : 'paglierani'}
+        authenticate(password='justin', **kwargs)
+        dne = MockHasher.hash_count
+        self.assertEqual(exists, dne) #counts should be the same
+
 
 @skipIfCustomUser
 class ModelBackendTest(BaseModelBackendTest, TestCase):
