diff --git a/djblets/auth/ratelimit.py b/djblets/auth/ratelimit.py
new file mode 100644
index 0000000000000000000000000000000000000000..f704494d112f2ee859ca3b6c5bbea558f3ed56d5
--- /dev/null
+++ b/djblets/auth/ratelimit.py
@@ -0,0 +1,35 @@
+"""Utility for rate-limiting login attempts"""
+
+from __future__ import unicode_literals
+
+from django.conf import settings
+
+
+periods = {
+    's': 1,
+    'm': 60,
+    'h': 60 * 60,
+    'd': 24 * 60 * 60,
+}
+
+methods = {'POST'}
+
+def user_or_ip(request):
+	''' 
+	Obtain user ID or IP address from request.
+
+	If the user is authenticated, the user ID will be returned.
+	Otherwise, the IP address of the client is returned instead.
+
+	Args:
+		request (HttpRequest):
+			The HTTP request from the client.
+
+	Returns:
+		String value for user ID or IP address.
+	'''
+	if request.user.is_authenticated():
+ 		return str(request.user.pk)
+	
+	return request.META['REMOTE_ADDR']
+
diff --git a/djblets/settings.py b/djblets/settings.py
index 18e42d8f54a8e634bb8c604b046e5df1cff38969..e298735658ebf9206d190b56ebc8ebde44e1bc72 100644
--- a/djblets/settings.py
+++ b/djblets/settings.py
@@ -21,6 +21,7 @@ DJBLETS_ROOT = os.path.abspath(os.path.dirname(__file__))
 HTDOCS_ROOT = os.path.join(DJBLETS_ROOT, 'htdocs')
 STATIC_ROOT = os.path.join(HTDOCS_ROOT, 'static')
 STATIC_URL = '/'
+LOGIN_LIMIT_RATE = '5/m'
 
 STATICFILES_DIRS = (
     os.path.join(DJBLETS_ROOT, 'static'),
