diff --git a/reviewboard/accounts/backends.py b/reviewboard/accounts/backends.py
index 76e8227f0a6f03f8e35b3bcd1ab2ea5bcd127bb1..67f006181be2867e80cfb96d377bc3113d67ed53 100644
--- a/reviewboard/accounts/backends.py
+++ b/reviewboard/accounts/backends.py
@@ -1,5 +1,6 @@
 from __future__ import unicode_literals
 
+import hashlib
 import logging
 import pkg_resources
 import re
@@ -25,7 +26,8 @@ from reviewboard.accounts.forms.auth import (ActiveDirectorySettingsForm,
                                              LDAPSettingsForm,
                                              NISSettingsForm,
                                              StandardAuthSettingsForm,
-                                             X509SettingsForm)
+                                             X509SettingsForm,
+                                             HTTPBasicSettingsForm)
 from reviewboard.accounts.models import LocalSiteProfile
 from reviewboard.site.models import LocalSite
 
@@ -277,6 +279,58 @@ class StandardAuthBackend(AuthBackend, ModelBackend):
         return super(StandardAuthBackend, self).has_perm(user, perm, obj)
 
 
+class HTTPDigestBackend(AuthBackend):
+    """Authenticate against a user in a digest password file."""
+    backend_id = 'digest'
+    name = _('HTTP Digest Authentication')
+    settings_form = HTTPBasicSettingsForm
+    login_instructions = \
+        _('Use your standard username and password.')
+
+    def authenticate(self, username, password):
+        username = username.strip()
+
+        digest_password = hashlib.md5("{0}:{1}:{2}".format(
+            username, settings.DIGEST_REALM, password)).hexdigest()
+
+        try:
+            with open(settings.DIGEST_FILE_LOCATION, 'r') as passwd_file:
+                for line_no, line in enumerate(passwd_file):
+                    try:
+                        user, realm, passwd = line.strip().split(':')
+
+                        if user == username and passwd == digest_password:
+                            return self.get_or_create_user(username, None)
+                        else:
+                            continue
+
+                    except ValueError as e:
+                        logging.error("Error in password file, does not "
+                                      "contain a user, realm and password. "
+                                      "Line: %d: %s", line_no, e,
+                                      exc_info=True)
+                        break
+
+        except IOError as e:
+            logging.error("HTTP Digest error: failed opening the"
+                          "opening the password file. Error: %s", e,
+                          exc_info=True)
+
+        return None
+
+    def get_or_create_user(self, username, request):
+        try:
+            user = User.objects.get(username=username)
+
+        except User.DoesNotExist:
+            user = User(username=username, password='')
+            user.is_staff = False
+            user.is_superuser = False
+            user.set_unusable_password()
+            user.save()
+        return user
+
+
 class NISBackend(AuthBackend):
     """Authenticate against a user on an NIS server."""
     backend_id = 'nis'
diff --git a/reviewboard/accounts/forms/auth.py b/reviewboard/accounts/forms/auth.py
index 5cebb1eb056fd22747dc4ef1a18327b13235c59f..1dcac57aa1d1984731d9b914fd5c326c974b9432 100644
--- a/reviewboard/accounts/forms/auth.py
+++ b/reviewboard/accounts/forms/auth.py
@@ -145,6 +145,22 @@ class StandardAuthSettingsForm(SiteSettingsForm):
         title = _('Basic Authentication Settings')
 
 
+class HTTPBasicSettingsForm(SiteSettingsForm):
+    auth_digest_file_location = forms.CharField(
+        label=_(".htpasswd File location"),
+        help_text=_("Location of the .htpasswd file which "
+                    "stores the usernames and passwords in digest format"),
+        widget=forms.TextInput(attrs={'size': '60'}))
+
+    auth_digest_realm = forms.CharField(
+        label=_("HTTP Digest Realm"),
+        help_text=_("Realm used for HTTP Digest authentication"),
+        widget=forms.TextInput(attrs={'size': '40'}))
+
+    class Meta:
+        title = _('HTTP Digest Authentication Settings')
+
+
 class LDAPSettingsForm(SiteSettingsForm):
     # TODO: Invent a URIField and use it.
     auth_ldap_uri = forms.CharField(
diff --git a/reviewboard/admin/management/sites.py b/reviewboard/admin/management/sites.py
index c7a3ee883e5c6fd4f90f095a09ac4ca51a86e4c1..c012578d53fc7e2530efaeac24ef267aa962f455 100644
--- a/reviewboard/admin/management/sites.py
+++ b/reviewboard/admin/management/sites.py
@@ -74,6 +74,7 @@ auth_backend_map = {
     'django.contrib.auth.backends.ModelBackend': 'builtin',
     'reviewboard.accounts.backends.NISBackend':  'nis',
     'reviewboard.accounts.backends.LDAPBackend': 'ldap',
+    'reviewboard.accounts.backends.HTTPDigestBackend': 'digest',
 }
 
 
diff --git a/reviewboard/admin/siteconfig.py b/reviewboard/admin/siteconfig.py
index d378154a1cbf2e263d81c823b0013f25c5fb92c5..98ba867d3e9df4a5b3ca018cce86ed7a2f093ff5 100644
--- a/reviewboard/admin/siteconfig.py
+++ b/reviewboard/admin/siteconfig.py
@@ -60,6 +60,8 @@ storage_backend_map = {
 # A mapping of siteconfig setting names to Django settings.py names.
 # This also contains all the djblets-provided mappings as well.
 settings_map = {
+    'auth_digest_file_location':      'DIGEST_FILE_LOCATION',
+    'auth_digest_realm':              'DIGEST_REALM',
     'auth_ldap_anon_bind_uid':        'LDAP_ANON_BIND_UID',
     'auth_ldap_anon_bind_passwd':     'LDAP_ANON_BIND_PASSWD',
     'auth_ldap_given_name_attribute': 'LDAP_GIVEN_NAME_ATTRIBUTE',
diff --git a/setup.py b/setup.py
index 2ce673a1076ffa2ee2aa8f4de5dc1f452deabca4..ee1714f116dd7cbd62520835a25d3e223cd027e5 100755
--- a/setup.py
+++ b/setup.py
@@ -190,6 +190,7 @@ setup(name=PACKAGE_NAME,
               'ldap = reviewboard.accounts.backends:LDAPBackend',
               'nis = reviewboard.accounts.backends:NISBackend',
               'x509 = reviewboard.accounts.backends:X509Backend',
+              'digest = reviewboard.accounts.backends:HTTPDigestBackend',
           ],
       },
       cmdclass=cmdclasses,
