Skip to content

Commit

Permalink
Fallback to latin-1 encoding for credentials when utf-8 fails (Fixes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed May 26, 2022
1 parent b42168e commit 4a92b75
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
13 changes: 8 additions & 5 deletions src/flask_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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})

Expand Down
15 changes: 13 additions & 2 deletions tests/test_basic_verify_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ''
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 4a92b75

Please sign in to comment.