From 4dcfa3d47d811206e6e724eabc046ba0f8071390 Mon Sep 17 00:00:00 2001 From: Helen Kosova Date: Thu, 24 May 2018 20:38:29 +0300 Subject: [PATCH 1/2] Fixed incorrect Bearer token extraction and added tests --- httpbin/core.py | 6 +++--- test_httpbin.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/httpbin/core.py b/httpbin/core.py index 0a00a82..08774ea 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -907,13 +907,13 @@ def bearer_auth(): 401: description: Unsuccessful authentication. """ - if 'Authorization' not in request.headers: + authorization = request.headers.get('Authorization') + if not (authorization and authorization.startswith('Bearer ')): response = app.make_response('') response.headers['WWW-Authenticate'] = 'Bearer' response.status_code = 401 return response - authorization = request.headers.get('Authorization') - token = authorization.lstrip('Bearer ') + token = authorization.split('Bearer ', 1).pop() return jsonify(authenticated=True, token=token) diff --git a/test_httpbin.py b/test_httpbin.py index 27a9042..9db3515 100755 --- a/test_httpbin.py +++ b/test_httpbin.py @@ -280,6 +280,37 @@ class HttpbinTestCase(unittest.TestCase): response = self.app.get('/brotli') self.assertEqual(response.status_code, 200) + def test_bearer_auth(self): + token = 'abcd1234' + response = self.app.get( + '/bearer', + headers={'Authorization': 'Bearer ' + token} + ) + self.assertEqual(response.status_code, 200) + assert json.loads(response.data.decode('utf-8'))['token'] == token + + def test_bearer_auth_with_wrong_authorization_type(self): + """Sending an non-Bearer Authorization header to /bearer should return a 401""" + auth_headers = ( + ('Authorization', 'Basic 1234abcd'), + ('Authorization', ''), + ('', '') + ) + for header in auth_headers: + response = self.app.get( + '/bearer', + headers={header[0]: header[1]} + ) + self.assertEqual(response.status_code, 401) + + def test_bearer_auth_with_missing_token(self): + """Sending an 'Authorization: Bearer' header with no token to /bearer should return a 401""" + response = self.app.get( + '/bearer', + headers={'Authorization': 'Bearer'} + ) + self.assertEqual(response.status_code, 401) + def test_digest_auth_with_wrong_password(self): auth_header = 'Digest username="user",realm="wrong",nonce="wrong",uri="/digest-auth/user/passwd/MD5",response="wrong",opaque="wrong"' response = self.app.get( From fcef66c11718f055818cb4c37acd8c1d5b3c03ac Mon Sep 17 00:00:00 2001 From: Helen Kosova Date: Fri, 25 May 2018 11:18:34 +0300 Subject: [PATCH 2/2] Replaced str.split() with slice --- httpbin/core.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httpbin/core.py b/httpbin/core.py index 08774ea..6efeb01 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -913,7 +913,8 @@ def bearer_auth(): response.headers['WWW-Authenticate'] = 'Bearer' response.status_code = 401 return response - token = authorization.split('Bearer ', 1).pop() + slice_start = len('Bearer ') + token = authorization[slice_start:] return jsonify(authenticated=True, token=token)