From 86976a27e7aa9222afc0695c240b0ea7cc8e362b Mon Sep 17 00:00:00 2001 From: "Kali Kaneko (leap communications)" Date: Wed, 9 Nov 2016 20:34:51 +0100 Subject: [feature] authentication classes and tests --- tests/unit/core/test_web_api.py | 105 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/unit/core/test_web_api.py (limited to 'tests') diff --git a/tests/unit/core/test_web_api.py b/tests/unit/core/test_web_api.py new file mode 100644 index 0000000..f440417 --- /dev/null +++ b/tests/unit/core/test_web_api.py @@ -0,0 +1,105 @@ +import base64 + +from twisted.cred import portal +from twisted.trial import unittest +from twisted.web.test.test_web import DummyRequest +from twisted.web import resource + +from leap.bitmask.core import _web + + +def b64encode(s): + return base64.b64encode(s).strip() + + +class APIMixin: + """ + L{TestCase} mixin class which defines a number of tests for + L{basic.BasicCredentialFactory}. Because this mixin defines C{setUp}, it + must be inherited before L{TestCase}. + """ + def setUp(self): + self.request = self.makeRequest() + + api = AuthTestResource() + self.realm = _web.HttpPasswordRealm(api) + tokens = {'testuser': 'token'} + checker = _web.TokenDictChecker(tokens) + self.portal = portal.Portal(self.realm, [checker]) + + def makeRequest(self, method=b'GET', clientAddress=None): + """ + Create a request object to be passed to + TokenCredentialFactory.decode along with a response value. + Override this in a subclass. + """ + raise NotImplementedError("%r did not implement makeRequest" % ( + self.__class__,)) + + +class WhitelistedResourceTests(APIMixin, unittest.TestCase): + + def makeRequest(self, method=b'GET', clientAddress=None, path='/'): + """ + Create a L{DummyRequest} (change me to create a + L{twisted.web.http.Request} instead). + """ + request = DummyRequest(b'/') + request.method = method + request.client = clientAddress + request.path = path + return request + + def test_render_returns_unauthorized_by_default(self): + """ + By default, a Whitelisted resource renders with a 401 response code and + a I{WWW-Authenticate} header and puts a simple unauthorized message + into the response body. + """ + protected = _web.WhitelistHTTPAuthSessionWrapper( + self.portal, + [_web.TokenCredentialFactory('localhost')]) + request = self.makeRequest(method='POST', path='/') + request.render(protected) + assert request.responseCode == 401 + + auth_header = request.responseHeaders.getRawHeaders( + b'www-authenticate') + assert auth_header == [b'token realm="localhost"'] + assert b'Unauthorized' == b''.join(request.written) + + def test_whitelisted_resource_does_render(self): + protected = _web.WhitelistHTTPAuthSessionWrapper( + self.portal, + [_web.TokenCredentialFactory('localhost')], + whitelist=['/whitelisted']) + request = self.makeRequest(method='GET', path='/whitelisted') + request.render(protected) + assert b'dummyGET' == b''.join(request.written) + + def test_good_token_authenticates(self): + protected = _web.WhitelistHTTPAuthSessionWrapper( + self.portal, + [_web.TokenCredentialFactory('localhost')], + whitelist=[]) + request = self.makeRequest(method='GET', path='/') + authorization = b64encode(b'testuser:token') + request.requestHeaders.addRawHeader(b'authorization', + b'Token ' + authorization) + request.render(protected) + assert b'dummyGET' == b''.join(request.written) + + def test_session_does_not_use_cookies(self): + # TODO + pass + + +class AuthTestResource(resource.Resource): + + isLeaf = True + + def render_GET(self, request): + return "dummyGET" + + def render_POST(self, request): + return "dummyPOST" -- cgit v1.2.3