def init(self): '''This method is invoked automatically in order to setup common dependencies for all test cases.''' self._symmetric_encryptor = Mock() self._public_encryptor = PublicTokenEncryption(self._symmetric_encryptor) self._token_iv = Mock() self._token_key = Mock()
class PublicTokenEncryptionTests(FantasticoUnitTestsCase): '''This class provides tests suite for public token encryption algorithm.''' _symmetric_encryptor = None _public_encryptor = None _token_iv = None _token_key = None def init(self): '''This method is invoked automatically in order to setup common dependencies for all test cases.''' self._symmetric_encryptor = Mock() self._public_encryptor = PublicTokenEncryption(self._symmetric_encryptor) self._token_iv = Mock() self._token_key = Mock() def test_encrypt_token_ok(self): '''This test case ensures a given token object can be correctly encrypted by public token encryption.''' token = Token({"client_id": 123, "type": "access", "attr1": "cool-attr"}) self._symmetric_encryptor.encrypt_token = Mock(return_value="test") encrypted_str = self._public_encryptor.encrypt_token(token, self._token_iv, self._token_key) self.assertIsNotNone(encrypted_str) encrypted_str = base64.b64decode(encrypted_str.encode()) public_token = json.loads(encrypted_str.decode()) self.assertIsNotNone(public_token) self.assertEqual(token.client_id, public_token.get("client_id")) self.assertEqual(token.type, public_token.get("type")) self.assertEqual("test", public_token.get("encrypted")) self._symmetric_encryptor.encrypt_token.assert_called_once_with(token, self._token_iv, self._token_key) def test_encrypt_token_missingtoken(self): '''This test case ensures encrypt fails if no token is specified.''' self._test_encrypt_missing_arg("token", None, None, None) def test_encrypt_token_missingiv(self): '''This test case ensures encrypt fails if no token_iv is specified.''' self._test_encrypt_missing_arg("token_iv", Mock(), None, None) def test_encrypt_token_missingkey(self): '''This test case ensures encrypt fails if no token_key is specified.''' self._test_encrypt_missing_arg("token_key", Mock(), Mock(), None) def _test_encrypt_missing_arg(self, attr_name, token, token_iv, token_key): '''This method provides a template for testing encrypt_token with various arguments. It automatically assert for invalid token descriptor exception being raised.''' with self.assertRaises(OAuth2InvalidTokenDescriptorError) as ctx: self._public_encryptor.encrypt_token(token, token_iv, token_key) self.assertEqual(attr_name, ctx.exception.attr_name) def test_encrypt_token_symmetric_oauth2ex(self): '''This test case ensures all oauth2 concrete exceptions raised during symmetric encryption are bubbled up.''' token = Token({}) ex = OAuth2Error(error_code= -1, msg="Simple msg.", http_code=403) self._symmetric_encryptor.encrypt_token = Mock(side_effect=ex) with self.assertRaises(OAuth2Error) as ctx: self._public_encryptor.encrypt_token(token, self._token_iv, self._token_key) self.assertEqual(ex, ctx.exception) def test_encrypt_token_symmetric_ex(self): '''This test case ensures all unexpected exception raised by symmetric encryptor are not bubbled up.''' token = Token({}) ex = Exception("Unexpected error.") self._symmetric_encryptor.encrypt_token = Mock(side_effect=ex) with self.assertRaises(OAuth2TokenEncryptionError): self._public_encryptor.encrypt_token(token, self._token_iv, self._token_key) def test_encrypt_token_clientrepo_ok(self): '''This test case ensures a token can be encrypted without specifying the token encryption vectors.''' token_iv = "token iv".encode() token_key = "token key".encode() token = Token({"client_id": 123, "type": "access", "attr1": "cool-attr"}) client = Client(token_iv=base64.b64encode(token_iv).decode(), token_key=base64.b64encode(token_key).decode()) client_repo = Mock() client_repo.load = Mock(return_value=client) self._symmetric_encryptor.encrypt_token = Mock(return_value="test") encrypted_str = self._public_encryptor.encrypt_token(token, client_repo=client_repo) self.assertIsNotNone(encrypted_str) encrypted_str = base64.b64decode(encrypted_str.encode()) public_token = json.loads(encrypted_str.decode()) self.assertIsNotNone(public_token) self.assertEqual(token.client_id, public_token.get("client_id")) self.assertEqual(token.type, public_token.get("type")) self.assertEqual("test", public_token.get("encrypted")) client_repo.load.assert_called_once_with(token.client_id) self._symmetric_encryptor.encrypt_token.assert_called_once_with(token, token_iv, token_key) def test_encrypt_clientrepo_ex(self): '''This test case ensures all client repo exceptions are casted to oauth2 concrete exceptions.''' client_repo = Mock() client_repo.load = Mock(side_effect=Exception("Unexpected exception.")) with self.assertRaises(OAuth2InvalidClientError): self._public_encryptor.encrypt_token(Token({"client_id": "mock-client"}), client_repo=client_repo) def test_decrypt_token_ok(self): '''This test case ensures a given token can be decrypted correctly by public token provider.''' encrypted_token_desc = {"client_id": "abc", "type": "access", "attr1": "attr test"} token_desc = {"client_id": "abc", "type": "access", "encrypted": "abc"} encrypted_str = base64.b64encode(json.dumps(token_desc).encode()) encrypted_token = Token(encrypted_token_desc) self._symmetric_encryptor.decrypt_token = Mock(return_value=encrypted_token) token = self._public_encryptor.decrypt_token(encrypted_str.decode(), self._token_iv, self._token_key) self.assertIsNotNone(token) self.assertEqual(encrypted_token, token) self._symmetric_encryptor.decrypt_token.assert_called_once_with("abc", self._token_iv, self._token_key) def test_decrypt_token_missingdesc(self): '''This test case ensures a given token can not be decrypted by public token provider if it's null or empty.''' for encrypted_str in [None, "", " "]: with self.assertRaises(OAuth2InvalidTokenDescriptorError) as ctx: self._public_encryptor.decrypt_token(encrypted_str, self._token_iv, self._token_key) self.assertEqual("encrypted_str", ctx.exception.attr_name) def test_decrypt_symmetric_oauth2ex(self): '''This test case ensures all oauth2 exception caused by symmetric provider are bubbled up.''' public_token_desc = {"client_id": "abc", "type": "access", "encrypted": "long encrypted token"} encrypted_str = base64.b64encode(json.dumps(public_token_desc).encode()).decode() ex = OAuth2Error(error_code= -1, msg="Unexpected error") self._symmetric_encryptor.decrypt_token = Mock(side_effect=ex) with self.assertRaises(OAuth2Error) as ctx: self._public_encryptor.decrypt_token(encrypted_str, self._token_iv, self._token_key) self.assertEqual(ex, ctx.exception) self._symmetric_encryptor.decrypt_token.assert_called_once_with(public_token_desc["encrypted"], self._token_iv, self._token_key) def test_decrypt_symmetric_ex(self): '''This test case ensures all unexpected exceptions (non oauth2) raised by symmetric encryptor are correctly converted to concrete oauth2 exceptions.''' public_token_desc = {"client_id": "abc", "type": "access", "encrypted": "long encrypted token"} encrypted_str = base64.b64encode(json.dumps(public_token_desc).encode()).decode() ex = Exception("Unexpected exception.") self._symmetric_encryptor.decrypt_token = Mock(side_effect=ex) with self.assertRaises(OAuth2TokenEncryptionError): self._public_encryptor.decrypt_token(encrypted_str, self._token_iv, self._token_key) self._symmetric_encryptor.decrypt_token.assert_called_once_with(public_token_desc["encrypted"], self._token_iv, self._token_key) def test_decrypt_client_repo_ok(self): '''This test case ensures decrypt works ok without specified token encryption vectors.''' token_iv = "token iv".encode() token_key = "token_key".encode() encrypted_token_desc = {"client_id": "abc", "type": "access", "attr1": "attr test"} token_desc = {"client_id": "abc", "type": "access", "encrypted": "abc"} encrypted_str = base64.b64encode(json.dumps(token_desc).encode()) encrypted_token = Token(encrypted_token_desc) client = Client(token_iv=base64.b64encode(token_iv).decode(), token_key=base64.b64encode(token_key).decode()) client_repo = Mock() client_repo.load = Mock(return_value=client) self._symmetric_encryptor.decrypt_token = Mock(return_value=encrypted_token) token = self._public_encryptor.decrypt_token(encrypted_str.decode(), client_repo=client_repo) self.assertIsNotNone(token) self.assertEqual(encrypted_token, token) client_repo.load.assert_called_once_with(token_desc["client_id"]) self._symmetric_encryptor.decrypt_token.assert_called_once_with("abc", token_iv, token_key) def test_decrypt_client_repo_ex(self): '''This test case ensures all exceptions from client repository are casted to oauth2 concrete exceptions.''' token_desc = {"client_id": "abc", "type": "access", "encrypted": "abc"} encrypted_str = base64.b64encode(json.dumps(token_desc).encode()).decode() client_repo = Mock() client_repo.load = Mock(side_effect=Exception("Unexpected exception.")) with self.assertRaises(OAuth2InvalidClientError): self._public_encryptor.decrypt_token(encrypted_str, client_repo=client_repo)