From bc5429b6f79d4aa1936a604a43f74448c2a1fb51 Mon Sep 17 00:00:00 2001 From: Bruno Souza <12611098+brnosouza@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:31:16 -0300 Subject: [PATCH] Add support for using utf8 compatible keys (#109) * Add support for using utf8 compatible keys - Change: cache key arguments accept utf8 strings * Improve testcase readability --------- Co-authored-by: Bruno Souza --- security/auth_throttling/__init__.py | 12 ++++++++++-- tests/tests.py | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/security/auth_throttling/__init__.py b/security/auth_throttling/__init__.py index a0e3258..f82675e 100644 --- a/security/auth_throttling/__init__.py +++ b/security/auth_throttling/__init__.py @@ -1,6 +1,7 @@ import hashlib import logging import time +import urllib.parse from math import ceil from django.contrib.auth import REDIRECT_FIELD_NAME @@ -43,6 +44,13 @@ def delay_message(remainder): return _("%d seconds") % ceil(remainder) +def _to_ascii_compatible(value: str): + if not value.isascii(): + value = urllib.parse.quote(value) + + return value + + def _key(counter_type, counter_name): """ We store a hashed version of the key because what we generate can be @@ -50,8 +58,8 @@ def _key(counter_type, counter_name): that memcache doesn't like. """ key = "security.authentication_throttling.%s:%s" % ( - counter_type, - counter_name, + _to_ascii_compatible(counter_type), + _to_ascii_compatible(counter_name), ) return hashlib.sha256(key.encode("ascii")).hexdigest() diff --git a/tests/tests.py b/tests/tests.py index 29acd62..d645b90 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -18,7 +18,7 @@ from security.auth_throttling import Middleware as AuthThrottlingMiddleware from security.auth_throttling import (attempt_count, default_delay_function, delay_message, increment_counters, - reset_counters) + reset_counters, throttling_delay) from security.middleware import (BaseMiddleware, ContentSecurityPolicyMiddleware, DoNotTrackMiddleware, @@ -1071,3 +1071,20 @@ def test_improper_configuration_raises(self): "REFERRER_POLICY", "invalid", ) + + +class UnicodeDataTests(TestCase): + USERNAME = "ñoñó1234" + IP_ADDRESS = "127.0.0.1" + + def test_unicode_data_in_cache_key(self): + self._execute_with_unicode_data(self.USERNAME, self.IP_ADDRESS) + + def _execute_with_unicode_data(self, username, ip): + try: + increment_counters(username=username, ip=ip) + reset_counters(username=username, ip=ip) + throttling_delay(username=username, ip=ip) + attempt_count(attempt_type="auth", id=username) + except Exception: + self.fail("Unicode data not allowed")