Skip to content

Commit

Permalink
Add option to use ha1 combination as password instead of plain text p…
Browse files Browse the repository at this point in the history
…assword
  • Loading branch information
ps committed Jan 24, 2015
1 parent fc34cc5 commit c84429f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
10 changes: 7 additions & 3 deletions flask_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ def authenticate(self, auth, stored_password):


class HTTPDigestAuth(HTTPAuth):
def __init__(self):
def __init__(self, use_ha1_pw = False):
super(HTTPDigestAuth, self).__init__()
self.use_ha1_pw = use_ha1_pw
self.random = SystemRandom()
try:
self.random.random()
Expand All @@ -119,8 +120,11 @@ def authenticate(self, auth, password):
if auth.nonce != session.get("auth_nonce") or \
auth.opaque != session.get("auth_opaque"):
return False
a1 = auth.username + ":" + auth.realm + ":" + password
ha1 = md5(a1.encode('utf-8')).hexdigest()
if self.use_ha1_pw:
ha1 = password
else:
a1 = auth.username + ":" + auth.realm + ":" + password
ha1 = md5(a1.encode('utf-8')).hexdigest()
a2 = request.method + ":" + auth.uri
ha2 = md5(a2.encode('utf-8')).hexdigest()
a3 = ha1 + ":" + auth.nonce + ":" + ha2
Expand Down
42 changes: 42 additions & 0 deletions test_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def md5(str):
str = str.encode('utf-8')
return basic_md5(str)

def get_ha1(user, pw, realm):
a1 = user + ":" + realm + ":" + pw
return md5(a1.encode('utf-8')).hexdigest()

class HTTPAuthTestCase(unittest.TestCase):
def setUp(self):
Expand All @@ -26,6 +29,16 @@ def setUp(self):
digest_auth = HTTPDigestAuth()
digest_auth_my_realm = HTTPDigestAuth()
digest_auth_my_realm.realm = 'My Realm'
digest_auth_ha1_pw = HTTPDigestAuth(use_ha1_pw = True)

@digest_auth_ha1_pw.get_password
def get_digest_password(username):
if username == 'susan':
return get_ha1(username, 'hello', digest_auth_ha1_pw.realm)
elif username == 'john':
return get_ha1(username, 'bye', digest_auth_ha1_pw.realm)
else:
return None

@basic_auth.get_password
def get_basic_password(username):
Expand Down Expand Up @@ -121,6 +134,11 @@ def basic_verify_auth_route():
def digest_auth_route():
return 'digest_auth:' + digest_auth.username()

@app.route('/digest_ha1_pw')
@digest_auth_ha1_pw.login_required
def digest_auth_ha1_pw_route():
return 'digest_auth:' + digest_auth.username()

@app.route('/digest-with-realm')
@digest_auth_my_realm.login_required
def digest_auth_my_realm_route():
Expand Down Expand Up @@ -258,6 +276,30 @@ def test_digest_auth_login_valid(self):
d['opaque'])})
self.assertEqual(response.data, b'digest_auth:john')

def test_digest_ha1_pw_auth_login_valid(self):
response = self.client.get('/digest_ha1_pw')
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 = 'john:' + d['realm'] + ':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="john",realm="{0}",'
'nonce="{1}",uri="/digest",response="{2}",'
'opaque="{3}"'.format(d['realm'],
d['nonce'],
auth_response,
d['opaque'])})
self.assertEqual(response.data, b'digest_auth:john')

def test_digest_auth_login_bad_realm(self):
response = self.client.get('/digest')
self.assertTrue(response.status_code == 401)
Expand Down

0 comments on commit c84429f

Please sign in to comment.