diff options
| author | Chris McDonough <chrism@plope.com> | 2013-10-20 16:17:51 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-10-20 16:17:51 -0400 |
| commit | 5688b6e76ba8059826ba6ff756b3e94b311320d2 (patch) | |
| tree | 5074ba1d0d378b91b640e234c9c9267fcbe06015 | |
| parent | 0264cc0c3d4ca091d4d5c8bd0c2fda38a3f8a0c7 (diff) | |
| parent | 2a6e6b3776b07589f8bbaaf4c72419f2bdf5e218 (diff) | |
| download | pyramid-5688b6e76ba8059826ba6ff756b3e94b311320d2.tar.gz pyramid-5688b6e76ba8059826ba6ff756b3e94b311320d2.tar.bz2 pyramid-5688b6e76ba8059826ba6ff756b3e94b311320d2.zip | |
Merge branch 'fix.basic-authentication-encodings'
| -rw-r--r-- | CHANGES.txt | 6 | ||||
| -rw-r--r-- | pyramid/authentication.py | 9 | ||||
| -rw-r--r-- | pyramid/tests/test_authentication.py | 26 |
3 files changed, 40 insertions, 1 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index e215b21bc..15b1b910e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -51,6 +51,12 @@ Bug Fixes - Remove unused ``renderer`` argument from ``Configurator.add_route``. +- Allow the ``BasicAuthenticationPolicy`` to work with non-ascii usernames + and passwords. The charset is not passed as part of the header and different + browsers alternate between UTF-8 and Latin-1, so the policy now attempts + to decode with UTF-8 first, and will fallback to Latin-1. + See https://github.com/Pylons/pyramid/pull/1170 + Documentation ------------- diff --git a/pyramid/authentication.py b/pyramid/authentication.py index 3c4077073..ec8ac0a41 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -1178,10 +1178,17 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy): return None if authmeth.lower() != 'basic': return None + try: - auth = b64decode(auth.strip()).decode('ascii') + authbytes = b64decode(auth.strip()) except (TypeError, binascii.Error): # can't decode return None + + try: + auth = authbytes.decode('utf-8') + except UnicodeDecodeError: + auth = authbytes.decode('latin-1') + try: username, password = auth.split(':', 1) except ValueError: # not enough values to unpack diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index 6e9e3920d..3ac8f2d61 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -1374,6 +1374,32 @@ class TestBasicAuthAuthenticationPolicy(unittest.TestCase): policy = self._makeOne(check) self.assertEqual(policy.authenticated_userid(request), 'chrisr') + def test_authenticated_userid_utf8(self): + import base64 + request = testing.DummyRequest() + inputs = (b'm\xc3\xb6rk\xc3\xb6:' + b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + request.headers['Authorization'] = 'Basic %s' % ( + base64.b64encode(inputs.encode('utf-8')).decode('latin-1')) + def check(username, password, request): + return [] + policy = self._makeOne(check) + self.assertEqual(policy.authenticated_userid(request), + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8')) + + def test_authenticated_userid_latin1(self): + import base64 + request = testing.DummyRequest() + inputs = (b'm\xc3\xb6rk\xc3\xb6:' + b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8') + request.headers['Authorization'] = 'Basic %s' % ( + base64.b64encode(inputs.encode('latin-1')).decode('latin-1')) + def check(username, password, request): + return [] + policy = self._makeOne(check) + self.assertEqual(policy.authenticated_userid(request), + b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8')) + def test_unauthenticated_userid_invalid_payload(self): import base64 request = testing.DummyRequest() |
