Merge pull request #201 from quinox/basicauth
Verify username/password with BasicAuth plugin
This commit is contained in:
commit
223e9608d7
28
tests/test_auth_plugins.py
Normal file
28
tests/test_auth_plugins.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
""" Unit tests for Authentication plugins"""
|
||||||
|
|
||||||
|
from websockify.auth_plugins import BasicHTTPAuth, AuthenticationError
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class BasicHTTPAuthTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.plugin = BasicHTTPAuth('Aladdin:open sesame')
|
||||||
|
|
||||||
|
def test_no_auth(self):
|
||||||
|
headers = {}
|
||||||
|
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
||||||
|
|
||||||
|
def test_invalid_password(self):
|
||||||
|
headers = {'Authorization': 'Basic QWxhZGRpbjpzZXNhbWUgc3RyZWV0'}
|
||||||
|
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
||||||
|
|
||||||
|
def test_valid_password(self):
|
||||||
|
headers = {'Authorization': 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
|
||||||
|
self.plugin.authenticate(headers, 'localhost', '1234')
|
||||||
|
|
||||||
|
def test_garbage_auth(self):
|
||||||
|
headers = {'Authorization': 'Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
|
||||||
|
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
@ -30,12 +30,13 @@ class InvalidOriginError(AuthenticationError):
|
|||||||
|
|
||||||
|
|
||||||
class BasicHTTPAuth(object):
|
class BasicHTTPAuth(object):
|
||||||
|
"""Verifies Basic Auth headers. Specify src as username:password"""
|
||||||
|
|
||||||
def __init__(self, src=None):
|
def __init__(self, src=None):
|
||||||
self.src = src
|
self.src = src
|
||||||
|
|
||||||
def authenticate(self, headers, target_host, target_port):
|
def authenticate(self, headers, target_host, target_port):
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
auth_header = headers.get('Authorization')
|
auth_header = headers.get('Authorization')
|
||||||
if auth_header:
|
if auth_header:
|
||||||
if not auth_header.startswith('Basic '):
|
if not auth_header.startswith('Basic '):
|
||||||
@ -46,18 +47,24 @@ class BasicHTTPAuth(object):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
raise AuthenticationError(response_code=403)
|
raise AuthenticationError(response_code=403)
|
||||||
|
|
||||||
user_pass = user_pass_raw.split(':', 1)
|
try:
|
||||||
|
# http://stackoverflow.com/questions/7242316/what-encoding-should-i-use-for-http-basic-authentication
|
||||||
|
user_pass_as_text = user_pass_raw.decode('ISO-8859-1')
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
raise AuthenticationError(response_code=403)
|
||||||
|
|
||||||
|
user_pass = user_pass_as_text.split(':', 1)
|
||||||
if len(user_pass) != 2:
|
if len(user_pass) != 2:
|
||||||
raise AuthenticationError(response_code=403)
|
raise AuthenticationError(response_code=403)
|
||||||
|
|
||||||
if not self.validate_creds:
|
if not self.validate_creds(*user_pass):
|
||||||
raise AuthenticationError(response_code=403)
|
raise AuthenticationError(response_code=403)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise AuthenticationError(response_code=401,
|
raise AuthenticationError(response_code=401,
|
||||||
response_headers={'WWW-Authenticate': 'Basic realm="Websockify"'})
|
response_headers={'WWW-Authenticate': 'Basic realm="Websockify"'})
|
||||||
|
|
||||||
def validate_creds(username, password):
|
def validate_creds(self, username, password):
|
||||||
if '%s:%s' % (username, password) == self.src:
|
if '%s:%s' % (username, password) == self.src:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user