summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/pixelated/account_recovery.py31
-rw-r--r--service/pixelated/application.py9
-rw-r--r--service/pixelated/authentication.py11
-rw-r--r--service/pixelated/resources/backup_account_resource.py23
-rw-r--r--service/pixelated/resources/login_resource.py2
-rw-r--r--service/pixelated/resources/root_resource.py2
-rw-r--r--service/requirements.txt2
-rw-r--r--service/test/unit/resources/test_backup_account_resource.py45
-rw-r--r--service/test/unit/resources/test_login_resource.py51
-rw-r--r--service/test/unit/test_account_recovery.py33
-rw-r--r--service/test/unit/test_application.py49
-rw-r--r--service/test/unit/test_authentication.py1
12 files changed, 209 insertions, 50 deletions
diff --git a/service/pixelated/account_recovery.py b/service/pixelated/account_recovery.py
new file mode 100644
index 00000000..405b572a
--- /dev/null
+++ b/service/pixelated/account_recovery.py
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2017 ThoughtWorks, Inc.
+#
+# Pixelated is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pixelated is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+from twisted.internet.defer import inlineCallbacks, returnValue
+import traceback
+
+
+class AccountRecovery(object):
+ def __init__(self, session):
+ self._session = session
+
+ @inlineCallbacks
+ def update_recovery_code(self, recovery_code):
+ try:
+ response = yield self._session.update_recovery_code(recovery_code)
+ returnValue(response)
+ except Exception as e:
+ traceback.print_exc(e)
+ raise
diff --git a/service/pixelated/application.py b/service/pixelated/application.py
index 46e5ba85..ef99d47c 100644
--- a/service/pixelated/application.py
+++ b/service/pixelated/application.py
@@ -30,6 +30,7 @@ from twisted.internet import reactor
from twisted.internet import ssl
from pixelated.adapter.welcome_mail import add_welcome_mail
+from pixelated.authentication import Authenticator
from pixelated.config import arguments
from pixelated.config import logger
from pixelated.config import services
@@ -60,7 +61,8 @@ def start_user_agent_in_single_user_mode(root_resource, services_factory, leap_h
services_factory.add_session(leap_session.user_auth.uuid, _services)
- root_resource.initialize(provider=leap_session.provider)
+ authenticator = Authenticator(leap_session.provider)
+ root_resource.initialize(provider=leap_session.provider, authenticator=authenticator)
# soledad needs lots of threads
reactor.getThreadPool().adjustPoolsize(5, 15)
@@ -153,14 +155,15 @@ def _setup_multi_user(args, root_resource, services_factory):
def set_up_protected_resources(root_resource, provider, services_factory, banner=None, authenticator=None):
+ auth = authenticator or Authenticator(provider)
session_checker = SessionChecker(services_factory)
realm = PixelatedRealm()
_portal = portal.Portal(realm, [session_checker, AllowAnonymousAccess()])
- anonymous_resource = LoginResource(services_factory, provider, disclaimer_banner=banner, authenticator=authenticator)
+ anonymous_resource = LoginResource(services_factory, provider, disclaimer_banner=banner, authenticator=auth)
protected_resource = PixelatedAuthSessionWrapper(_portal, root_resource, anonymous_resource, [])
- root_resource.initialize(provider, disclaimer_banner=banner, authenticator=authenticator)
+ root_resource.initialize(provider, disclaimer_banner=banner, authenticator=auth)
return protected_resource
diff --git a/service/pixelated/authentication.py b/service/pixelated/authentication.py
index 983086ce..27d6035a 100644
--- a/service/pixelated/authentication.py
+++ b/service/pixelated/authentication.py
@@ -30,6 +30,7 @@ class Authenticator(object):
def __init__(self, leap_provider):
self._leap_provider = leap_provider
self.domain = leap_provider.server_name
+ self.bonafide_sesssion = None
@inlineCallbacks
def authenticate(self, username, password):
@@ -49,9 +50,13 @@ class Authenticator(object):
def _bonafide_auth(self, user, password):
srp_provider = Api(self._leap_provider.api_uri)
credentials = Credentials(user, password)
- srp_auth = Session(credentials, srp_provider, self._leap_provider.local_ca_crt)
- yield srp_auth.authenticate()
- returnValue(Authentication(user, srp_auth.token, srp_auth.uuid, 'session_id', {'is_admin': False}))
+ self.bonafide_sesssion = Session(credentials, srp_provider, self._leap_provider.local_ca_crt)
+ yield self.bonafide_sesssion.authenticate()
+ returnValue(Authentication(user,
+ self.bonafide_sesssion.token,
+ self.bonafide_sesssion.uuid,
+ 'session_id',
+ {'is_admin': False}))
def clean_username(self, username):
if '@' not in username:
diff --git a/service/pixelated/resources/backup_account_resource.py b/service/pixelated/resources/backup_account_resource.py
index f1eeee53..d7e081d6 100644
--- a/service/pixelated/resources/backup_account_resource.py
+++ b/service/pixelated/resources/backup_account_resource.py
@@ -20,7 +20,9 @@ from xml.sax import SAXParseException
from pixelated.resources import BaseResource
from twisted.python.filepath import FilePath
from pixelated.resources import get_protected_static_folder
-from twisted.web.http import OK
+from pixelated.account_recovery import AccountRecovery
+from twisted.web.http import OK, NO_CONTENT, INTERNAL_SERVER_ERROR
+from twisted.web.server import NOT_DONE_YET
from twisted.web.template import Element, XMLFile, renderElement
@@ -34,8 +36,9 @@ class BackupAccountPage(Element):
class BackupAccountResource(BaseResource):
isLeaf = True
- def __init__(self, services_factory):
+ def __init__(self, services_factory, authenticator):
BaseResource.__init__(self, services_factory)
+ self._authenticator = authenticator
def render_GET(self, request):
request.setResponseCode(OK)
@@ -44,3 +47,19 @@ class BackupAccountResource(BaseResource):
def _render_template(self, request):
site = BackupAccountPage()
return renderElement(request, site)
+
+ def render_POST(self, request):
+ account_recovery = AccountRecovery(self._authenticator.bonafide_sesssion)
+
+ def update_response(response):
+ request.setResponseCode(NO_CONTENT)
+ request.finish()
+
+ def error_response(response):
+ request.setResponseCode(INTERNAL_SERVER_ERROR)
+ request.finish()
+
+ d = account_recovery.update_recovery_code("123")
+ d.addCallbacks(update_response)
+ d.addErrback(error_response)
+ return NOT_DONE_YET
diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py
index 5adfadf9..3e1200d7 100644
--- a/service/pixelated/resources/login_resource.py
+++ b/service/pixelated/resources/login_resource.py
@@ -86,7 +86,7 @@ class LoginResource(BaseResource):
BaseResource.__init__(self, services_factory)
self._disclaimer_banner = disclaimer_banner
self._provider = provider
- self._authenticator = authenticator or Authenticator(provider)
+ self._authenticator = authenticator
self._bootstrap_user_services = BootstrapUserServices(services_factory, provider)
static_folder = get_public_static_folder()
diff --git a/service/pixelated/resources/root_resource.py b/service/pixelated/resources/root_resource.py
index 320a1204..10d57c6f 100644
--- a/service/pixelated/resources/root_resource.py
+++ b/service/pixelated/resources/root_resource.py
@@ -91,7 +91,7 @@ class RootResource(BaseResource):
def initialize(self, provider=None, disclaimer_banner=None, authenticator=None):
self._child_resources.add('assets', File(self._protected_static_folder))
- self._child_resources.add('backup-account', BackupAccountResource(self._services_factory))
+ self._child_resources.add('backup-account', BackupAccountResource(self._services_factory, authenticator))
self._child_resources.add('sandbox', SandboxResource(self._protected_static_folder))
self._child_resources.add('keys', KeysResource(self._services_factory))
self._child_resources.add(AttachmentsResource.BASE_URL, AttachmentsResource(self._services_factory))
diff --git a/service/requirements.txt b/service/requirements.txt
index 7e544ef3..f1a01dfd 100644
--- a/service/requirements.txt
+++ b/service/requirements.txt
@@ -7,7 +7,7 @@ srp==1.0.6
whoosh==2.6.0
Twisted==16.1.1
-e 'git+https://0xacab.org/leap/leap_pycommon.git@master#egg=leap.common'
--e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask'
+-e 'git+https://0xacab.org/pixelated/bitmask-dev.git@recovery-code-and-key-expiry#egg=leap.bitmask'
-e 'git+https://0xacab.org/pixelated/soledad.git@master#egg=leap.soledad.common&subdirectory=common/'
-e 'git+https://0xacab.org/pixelated/soledad.git@master#egg=leap.soledad.client&subdirectory=client/'
-e .
diff --git a/service/test/unit/resources/test_backup_account_resource.py b/service/test/unit/resources/test_backup_account_resource.py
index 21ae5aab..e169062e 100644
--- a/service/test/unit/resources/test_backup_account_resource.py
+++ b/service/test/unit/resources/test_backup_account_resource.py
@@ -19,6 +19,7 @@ import os
from mock import MagicMock, patch
from twisted.trial import unittest
from twisted.web.test.requesthelper import DummyRequest
+from twisted.internet import defer
from pixelated.resources.backup_account_resource import BackupAccountResource
from test.unit.resources import DummySite
@@ -27,7 +28,7 @@ from test.unit.resources import DummySite
class TestBackupAccountResource(unittest.TestCase):
def setUp(self):
self.services_factory = MagicMock()
- self.resource = BackupAccountResource(self.services_factory)
+ self.resource = BackupAccountResource(self.services_factory, MagicMock())
self.web = DummySite(self.resource)
def test_get(self):
@@ -41,3 +42,45 @@ class TestBackupAccountResource(unittest.TestCase):
d.addCallback(assert_200_when_user_logged_in)
return d
+
+ @patch('pixelated.resources.backup_account_resource.AccountRecovery')
+ def test_post_updates_recovery_code(self, mock_account_recovery_init):
+ mock_account_recovery = MagicMock()
+ mock_account_recovery_init.return_value = mock_account_recovery
+ mock_account_recovery.update_recovery_code.return_value = defer.succeed("Success")
+ request = DummyRequest(['/backup-account'])
+ request.method = 'POST'
+ d = self.web.get(request)
+
+ def assert_update_recovery_code_called(_):
+ mock_account_recovery_init.assert_called_with(self.resource._authenticator.bonafide_sesssion)
+ mock_account_recovery.update_recovery_code.assert_called()
+
+ d.addCallback(assert_update_recovery_code_called)
+ return d
+
+ @patch('pixelated.resources.backup_account_resource.AccountRecovery.update_recovery_code')
+ def test_post_returns_successfully(self, mock_update_recovery_code):
+ mock_update_recovery_code.return_value = defer.succeed("Success")
+ request = DummyRequest(['/backup-account'])
+ request.method = 'POST'
+ d = self.web.get(request)
+
+ def assert_successful_response(_):
+ self.assertEqual(204, request.responseCode)
+
+ d.addCallback(assert_successful_response)
+ return d
+
+ @patch('pixelated.resources.backup_account_resource.AccountRecovery.update_recovery_code')
+ def test_post_returns_internal_server_error(self, mock_update_recovery_code):
+ mock_update_recovery_code.return_value = defer.fail(Exception)
+ request = DummyRequest(['/backup-account'])
+ request.method = 'POST'
+ d = self.web.get(request)
+
+ def assert_successful_response(_):
+ self.assertEqual(500, request.responseCode)
+
+ d.addCallback(assert_successful_response)
+ return d
diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py
index 733583a3..9f940bc6 100644
--- a/service/test/unit/resources/test_login_resource.py
+++ b/service/test/unit/resources/test_login_resource.py
@@ -16,7 +16,7 @@
import os
-from mock import patch
+from mock import patch, MagicMock
from mockito import mock, when, any as ANY
from twisted.cred.error import UnauthorizedLogin
from twisted.internet import defer
@@ -52,7 +52,7 @@ class TestLoginResource(unittest.TestCase):
def setUp(self):
self.services_factory = mock()
self.portal = mock()
- self.resource = LoginResource(self.services_factory, self.portal)
+ self.resource = LoginResource(self.services_factory, self.portal, authenticator=mock())
self.web = DummySite(self.resource)
def test_children_resources_are_unauthorized_when_not_logged_in(self):
@@ -170,7 +170,8 @@ class TestLoginPOST(unittest.TestCase):
def setUp(self):
self.services_factory = mock()
self.provider = mock()
- self.resource = LoginResource(self.services_factory, self.provider)
+ self.authenticator = MagicMock()
+ self.resource = LoginResource(self.services_factory, self.provider, authenticator=self.authenticator)
self.web = DummySite(self.resource)
self.request = DummyRequest([''])
@@ -185,10 +186,9 @@ class TestLoginPOST(unittest.TestCase):
user_auth.uuid = 'some_user_uuid'
self.user_auth = user_auth
- @patch('pixelated.authentication.Authenticator.authenticate')
@patch('twisted.web.util.redirectTo')
@patch('pixelated.resources.session.PixelatedSession.is_logged_in')
- def test_should_redirect_to_home_if_user_if_already_logged_in(self, mock_logged_in, mock_redirect, mock_authenticate):
+ def test_should_redirect_to_home_if_user_if_already_logged_in(self, mock_logged_in, mock_redirect):
mock_logged_in.return_value = True
when(self.services_factory).has_session(ANY()).thenReturn(True)
mock_redirect.return_value = "mocked redirection"
@@ -197,24 +197,23 @@ class TestLoginPOST(unittest.TestCase):
def assert_redirected_to_home(_):
mock_redirect.assert_called_once_with('/', self.request)
- self.assertFalse(mock_authenticate.called)
+ self.assertFalse(self.authenticator.authenticate.called)
d.addCallback(assert_redirected_to_home)
return d
@patch('pixelated.config.leap.BootstrapUserServices.setup')
@patch('twisted.web.util.redirectTo')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_should_redirect_to_login_with_error_flag_when_login_fails(self, mock_authenticate,
+ def test_should_redirect_to_login_with_error_flag_when_login_fails(self,
mock_redirect,
mock_user_bootstrap_setup):
- mock_authenticate.side_effect = UnauthorizedLogin()
+ self.authenticator.authenticate.side_effect = UnauthorizedLogin()
mock_redirect.return_value = "mocked redirection"
d = self.web.get(self.request)
def assert_redirected_to_login(_):
- mock_authenticate.assert_called_once_with(self.username, self.password)
+ self.authenticator.authenticate.assert_called_once_with(self.username, self.password)
mock_redirect.assert_called_once_with('/login?auth-error', self.request)
self.assertFalse(mock_user_bootstrap_setup.called)
self.assertFalse(self.resource.get_session(self.request).is_logged_in())
@@ -223,14 +222,13 @@ class TestLoginPOST(unittest.TestCase):
return d
@patch('pixelated.config.leap.BootstrapUserServices.setup')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_successful_login_responds_interstitial(self, mock_authenticate, mock_user_bootstrap_setup):
- mock_authenticate.return_value = self.user_auth
+ def test_successful_login_responds_interstitial(self, mock_user_bootstrap_setup):
+ self.authenticator.authenticate.return_value = self.user_auth
d = self.web.get(self.request)
def assert_interstitial_in_response(_):
- mock_authenticate.assert_called_once_with(self.username, self.password)
+ self.authenticator.authenticate.assert_called_once_with(self.username, self.password)
interstitial_js_in_template = '<script src="/public/interstitial.js"></script>'
self.assertIn(interstitial_js_in_template, self.request.written[0])
@@ -238,9 +236,8 @@ class TestLoginPOST(unittest.TestCase):
return d
@patch('pixelated.config.leap.BootstrapUserServices.setup')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_successful_login_runs_user_services_bootstrap_when_interstitial_loaded(self, mock_authenticate, mock_user_bootstrap_setup):
- mock_authenticate.return_value = self.user_auth
+ def test_successful_login_runs_user_services_bootstrap_when_interstitial_loaded(self, mock_user_bootstrap_setup):
+ self.authenticator.authenticate.return_value = self.user_auth
d = self.web.get(self.request)
@@ -251,9 +248,8 @@ class TestLoginPOST(unittest.TestCase):
return d
@patch('pixelated.config.leap.BootstrapUserServices.setup')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_successful_adds_cookies_to_indicate_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup):
- mock_authenticate.return_value = self.user_auth
+ def test_successful_adds_cookies_to_indicate_logged_in_status_when_services_are_loaded(self, mock_user_bootstrap_setup):
+ self.authenticator.authenticate.return_value = self.user_auth
irrelevant = None
mock_user_bootstrap_setup.return_value = defer.succeed(irrelevant)
@@ -266,9 +262,8 @@ class TestLoginPOST(unittest.TestCase):
return d
@patch('pixelated.resources.session.PixelatedSession.login_started')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_session_adds_login_started_status_after_authentication(self, mock_authenticate, mock_login_started):
- mock_authenticate.return_value = self.user_auth
+ def test_session_adds_login_started_status_after_authentication(self, mock_login_started):
+ self.authenticator.authenticate.return_value = self.user_auth
d = self.web.get(self.request)
@@ -280,9 +275,8 @@ class TestLoginPOST(unittest.TestCase):
@patch('pixelated.resources.session.PixelatedSession.login_successful')
@patch('pixelated.config.leap.BootstrapUserServices.setup')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_session_adds_login_successful_status_when_services_setup_finishes(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_successful):
- mock_authenticate.return_value = self.user_auth
+ def test_session_adds_login_successful_status_when_services_setup_finishes(self, mock_user_bootstrap_setup, mock_login_successful):
+ self.authenticator.authenticate.return_value = self.user_auth
mock_user_bootstrap_setup.return_value = defer.succeed(None)
d = self.web.get(self.request)
@@ -295,9 +289,8 @@ class TestLoginPOST(unittest.TestCase):
@patch('pixelated.resources.session.PixelatedSession.login_error')
@patch('pixelated.config.leap.BootstrapUserServices.setup')
- @patch('pixelated.authentication.Authenticator.authenticate')
- def test_session_adds_login_error_status_when_services_setup_gets_error(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_error):
- mock_authenticate.return_value = self.user_auth
+ def test_session_adds_login_error_status_when_services_setup_gets_error(self, mock_user_bootstrap_setup, mock_login_error):
+ self.authenticator.authenticate.return_value = self.user_auth
mock_user_bootstrap_setup.return_value = defer.fail(Exception('Could not setup user services'))
d = self.web.get(self.request)
diff --git a/service/test/unit/test_account_recovery.py b/service/test/unit/test_account_recovery.py
new file mode 100644
index 00000000..51ba3fd0
--- /dev/null
+++ b/service/test/unit/test_account_recovery.py
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2017 ThoughtWorks, Inc.
+#
+# Pixelated is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pixelated is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+
+from twisted.internet.defer import inlineCallbacks
+from twisted.trial import unittest
+
+from mock import patch, Mock
+
+from pixelated.account_recovery import AccountRecovery
+
+
+class AccountRecoveryTest(unittest.TestCase):
+
+ @inlineCallbacks
+ def test_update_recovery_code(self):
+ mock_session = Mock()
+ account_recovery = AccountRecovery(mock_session)
+
+ yield account_recovery.update_recovery_code('ABC')
+ mock_session.update_recovery_code.assert_called_once_with('ABC')
diff --git a/service/test/unit/test_application.py b/service/test/unit/test_application.py
index 178bab22..a61489fb 100644
--- a/service/test/unit/test_application.py
+++ b/service/test/unit/test_application.py
@@ -19,6 +19,7 @@ from twisted.trial import unittest
from leap.common.events import catalog as events
from mock import patch, MagicMock, ANY
import pixelated
+from pixelated.authentication import Authenticator
class ApplicationTest(unittest.TestCase):
@@ -97,22 +98,23 @@ class ApplicationTest(unittest.TestCase):
@patch('leap.common.events.client')
@patch('pixelated.application.reactor')
@patch('pixelated.application.services.Services')
- def test_should_log_user_out_if_invalid_soledad_token(self, services_mock, reactor_mock, events_mock):
+ def test_that_start_user_agent_binds_to_ssl_if_ssl_options(self, services_mock, reactor_mock, _):
+ # FIXME patch something closer, instead of leap.common
app_mock = MagicMock()
services_factory_mock = MagicMock()
-
- mock_service_log_user_out = MagicMock(return_value=None)
- services_factory_mock.destroy_session = mock_service_log_user_out
-
leap_session = MagicMock()
leap_session.fresh_account = False
- register_mock = events_mock.register
- register_mock.register.return_value = None
+ pixelated.application._ssl_options = lambda x, y: 'options'
+
+ config = ApplicationTest.MockConfig(12345, '127.0.0.1', sslkey="sslkey", sslcert="sslcert")
- config = ApplicationTest.MockConfig(12345, '127.0.0.1')
d = pixelated.application.start_user_agent_in_single_user_mode(app_mock, services_factory_mock, config.home, leap_session)
- pixelated.application.add_top_level_system_callbacks(d, services_factory_mock)
+ def _assert(_):
+ services_mock.assert_called_once_with(leap_session)
+
+ d.addCallback(_assert)
+ return d
def _assert_user_logged_out_using_uuid(_):
used_arguments = register_mock.call_args[0]
@@ -135,6 +137,27 @@ class ApplicationTest(unittest.TestCase):
return d
@patch('pixelated.application.reactor')
+ @patch('pixelated.application.services.Services')
+ def test_initialize_authenticator_in_single_user_mode(self, mock_services, _):
+ root_resources_mock = MagicMock()
+ services_factory_mock = MagicMock()
+ leap_session = MagicMock()
+ leap_session.fresh_account = False
+
+ d = pixelated.application.start_user_agent_in_single_user_mode(
+ root_resources_mock,
+ services_factory_mock,
+ "",
+ leap_session)
+
+ def assert_root_resource_initialize_called_with_authenticator(_):
+ authenticator = root_resources_mock.initialize.call_args[1]['authenticator']
+ self.assertIsInstance(authenticator, Authenticator)
+
+ d.addCallback(assert_root_resource_initialize_called_with_authenticator)
+ return d
+
+ @patch('pixelated.application.reactor')
@patch('pixelated.application._setup_multi_user')
def test_should_defer_fail_errors_during_multi_user_start_site(self, mock_multi_user_bootstrap, reactor_mock):
args_mock = MagicMock()
@@ -170,3 +193,11 @@ class ApplicationTest(unittest.TestCase):
d.addErrback(_assert_the_same_error_is_relayed_in_the_deferred)
return d
+
+ def test_set_up_protected_resources_initializes_authenticator(self):
+ mock_root_resource = MagicMock()
+ mock_provider = MagicMock()
+ pixelated.application.set_up_protected_resources(mock_root_resource, mock_provider, MagicMock())
+
+ authenticator = mock_root_resource.initialize.call_args[1]['authenticator']
+ self.assertIsInstance(authenticator, Authenticator)
diff --git a/service/test/unit/test_authentication.py b/service/test/unit/test_authentication.py
index 8ef1bce8..7b260905 100644
--- a/service/test/unit/test_authentication.py
+++ b/service/test/unit/test_authentication.py
@@ -77,6 +77,7 @@ class AuthenticatorTest(unittest.TestCase):
self.assertEquals('username', resulting_auth.username)
self.assertEquals('some_token', resulting_auth.token)
self.assertEquals('some_uuid', resulting_auth.uuid)
+ self.assertEquals(mock_srp_auth, auth.bonafide_sesssion)
def test_username_without_domain_is_not_changed(self):
username_without_domain = 'username'