Repository: gvalkov/tornado-http-auth

Issue:
authenticate_user method raises binascii.Error when provided auth is not base64
`authenticate_user` method raises uncontrolled exception when the provided Authorization header is not base64. To reproduce the issue:

```
curl -i \
    -H 'Accept:application/json' \
    -H 'Authorization:Basic not_a_base64_string' \
    http://localhost:8000/protected
```



Discussion:

Patch:
diff --git a/tornado_http_auth.py b/tornado_http_auth.py
index 2c6efbb..cbe74c8 100644
--- a/tornado_http_auth.py
+++ b/tornado_http_auth.py
@@ -209,8 +209,11 @@ class BasicAuthMixin(object):
             raise self.SendChallenge()
 
         auth_data = auth_header.split(None, 1)[-1]
-        auth_data = base64.b64decode(auth_data).decode('ascii')
-        username, password = auth_data.split(':', 1)
+        try:
+            auth_data = base64.b64decode(auth_data, validate=True).decode('ascii')
+            username, password = auth_data.split(':', 1)
+        except (UnicodeDecodeError, binascii.Error):
+            raise self.SendChallenge()
 
         challenge = check_credentials_func(username)
         if not challenge:


Test patch:
diff --git a/tests/test_functional.py b/tests/test_functional.py
index d03680b..ca2a817 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -40,9 +40,14 @@ class AuthTest(AsyncHTTPTestCase):
         res = self.fetch('/basic')
         self.assertEqual(res.code, 401)
 
+        res = self.fetch('/basic', headers={'Authorization': 'Basic foo bar'})
+        self.assertEqual(res.code, 401)
+
         auth = '%s:%s' % ('user1', 'pass1')
         auth = b64encode(auth.encode('ascii'))
-        hdr = {'Authorization': 'Basic %s' % auth.decode('utf8')}
-        res = self.fetch('/basic', headers=hdr)
-        self.assertEqual(res.code, 200)
 
+        res = self.fetch('/basic', headers={'Authorization': 'Basic ___%s' % auth.decode('utf8')})
+        self.assertEqual(res.code, 401)
+
+        res = self.fetch('/basic', headers={'Authorization': 'Basic %s' % auth.decode('utf8')})
+        self.assertEqual(res.code, 200)