Skip to content

Commit

Permalink
fixes #5: correct handling of None return from get_password callback
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Mar 17, 2014
1 parent 051195d commit b94dc8e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 deletions.
6 changes: 2 additions & 4 deletions flask_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
This module provides Basic and Digest HTTP authentication for Flask routes.
:copyright: (C) 2013 by Miguel Grinberg.
:copyright: (C) 2014 by Miguel Grinberg.
:license: BSD, see LICENSE for more details.
"""

Expand Down Expand Up @@ -48,8 +48,6 @@ def decorated(*args, **kwargs):
if not auth:
return self.auth_error_callback()
password = self.get_password_callback(auth.username)
#if not password:
# return self.auth_error_callback()
if not self.authenticate(auth, password):
return self.auth_error_callback()
return f(*args, **kwargs)
Expand Down Expand Up @@ -102,7 +100,7 @@ def authenticate_header(self):
return 'Digest realm="' + self.realm + '",nonce="' + session["auth_nonce"] + '",opaque="' + session["auth_opaque"] + '"'

def authenticate(self, auth, password):
if not auth.username or not auth.realm or not auth.uri or not auth.nonce or not auth.response:
if not auth.username or not auth.realm or not auth.uri or not auth.nonce or not auth.response or not password:
return False
if auth.nonce != session.get("auth_nonce") or auth.opaque != session.get("auth_opaque"):
return False
Expand Down
30 changes: 25 additions & 5 deletions test_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def get_basic_password(username):
elif username == 'susan':
return 'bye'
else:
return 'other'
return None

@basic_auth_my_realm.get_password
def get_basic_password(username):
Expand All @@ -41,7 +41,7 @@ def get_basic_password(username):
elif username == 'susan':
return 'susanbye'
else:
return 'other'
return None

@basic_auth_my_realm.hash_password
def basic_auth_my_realm_hash_password(username, password):
Expand All @@ -58,7 +58,7 @@ def get_basic_custom_auth_get_password(username):
elif username == 'susan':
return md5('bye').hexdigest()
else:
return 'other'
return None

@basic_custom_auth.hash_password
def basic_custom_auth_hash_password(password):
Expand All @@ -79,7 +79,7 @@ def get_digest_password(username):
elif username == 'john':
return 'bye'
else:
return 'other'
return None

@digest_auth_my_realm.get_password
def get_digest_password(username):
Expand All @@ -88,7 +88,7 @@ def get_digest_password(username):
elif username == 'john':
return 'bye'
else:
return 'other'
return None

@app.route('/')
def index():
Expand Down Expand Up @@ -250,6 +250,26 @@ def test_digest_auth_login_invalid(self):
self.assertTrue('WWW-Authenticate' in response.headers)
self.assertTrue(re.match(r'^Digest realm="My Realm",nonce="[0-9a-f]+",opaque="[0-9a-f]+"$', response.headers['WWW-Authenticate']))

def test_digest_auth_login_invalid2(self):
response = self.client.get('/digest')
self.assertTrue(response.status_code == 401)
header = response.headers.get('WWW-Authenticate')
auth_type, auth_info = header.split(None, 1)
d = parse_dict_header(auth_info)

a1 = 'david:' + 'Authentication Required' + ':bye'
ha1 = md5(a1).hexdigest()
a2 = 'GET:/digest'
ha2 = md5(a2).hexdigest()
a3 = ha1 + ':' + d['nonce'] + ':' + ha2
auth_response = md5(a3).hexdigest()

response = self.client.get('/digest',
headers = { 'Authorization': 'Digest username="david",realm="' + d['realm'] + '",nonce="' + d['nonce'] + '",uri="/digest",response="' + auth_response + '",opaque="' + d['opaque'] + '"' })
self.assertTrue(response.status_code == 401)
self.assertTrue('WWW-Authenticate' in response.headers)
self.assertTrue(re.match(r'^Digest realm="Authentication Required",nonce="[0-9a-f]+",opaque="[0-9a-f]+"$', response.headers['WWW-Authenticate']))

def suite():
return unittest.makeSuite(HTTPAuthTestCase)

Expand Down

0 comments on commit b94dc8e

Please sign in to comment.