diff --git a/src/flask_httpauth.py b/src/flask_httpauth.py index eca596f..75414e9 100644 --- a/src/flask_httpauth.py +++ b/src/flask_httpauth.py @@ -217,15 +217,18 @@ def get_auth(self): value = request.headers[header].encode('utf-8') try: scheme, credentials = value.split(b' ', 1) - username, password = b64decode(credentials).split(b':', 1) + encoded_username, encoded_password = b64decode( + credentials).split(b':', 1) except (ValueError, TypeError): return None try: - username = username.decode('utf-8') - password = password.decode('utf-8') + username = encoded_username.decode('utf-8') + password = encoded_password.decode('utf-8') except UnicodeDecodeError: - username = None - password = None + # try to decode again with latin-1, which should always work + username = encoded_username.decode('latin1') + password = encoded_password.decode('latin1') + return Authorization( scheme, {'username': username, 'password': password}) diff --git a/tests/test_basic_verify_password.py b/tests/test_basic_verify_password.py index 4f383ab..bbd4465 100644 --- a/tests/test_basic_verify_password.py +++ b/tests/test_basic_verify_password.py @@ -21,6 +21,8 @@ def basic_verify_auth_verify_password(username, password): return password == 'hello' elif username == 'susan': return password == 'bye' + elif username == 'garçon': + return password == 'áéíóú' elif username == '': g.anon = True return True @@ -31,6 +33,8 @@ def basic_verify_auth_verify_password(username, password): return 'john' elif username == 'susan' and password == 'bye': return 'susan' + elif username == 'garçon' and password == 'áéíóú': + return 'garçon' elif username == '': g.anon = True return '' @@ -59,17 +63,24 @@ def basic_verify_auth_route(): self.client = app.test_client() def test_verify_auth_login_valid(self): - creds = base64.b64encode(b'susan:bye').decode('utf-8') + creds = base64.b64encode(b'susan:bye').decode() response = self.client.get( '/basic-verify', headers={'Authorization': 'Basic ' + creds}) self.assertEqual(response.data, b'basic_verify_auth:susan anon:False') + def test_verify_auth_login_valid_latin1(self): + creds = base64.b64encode('garçon:áéíóú'.encode('latin1')).decode() + response = self.client.get( + '/basic-verify', headers={'Authorization': 'Basic ' + creds}) + self.assertEqual(response.data.decode(), + 'basic_verify_auth:garçon anon:False') + def test_verify_auth_login_empty(self): response = self.client.get('/basic-verify') self.assertEqual(response.data, b'basic_verify_auth: anon:True') def test_verify_auth_login_invalid(self): - creds = base64.b64encode(b'john:bye').decode('utf-8') + creds = base64.b64encode(b'john:bye').decode() response = self.client.get( '/basic-verify', headers={'Authorization': 'Basic ' + creds}) self.assertEqual(response.status_code, 403)