def test_round_trip(self): """We can encrypt a message with a priv key and decrypt with a public key""" string_to_sign = "Hello world" # we compare the hash, rather than the message itself.... hashed = sha512(string_to_sign.encode('US-ASCII')).hexdigest() # load the public key pubkey = load_key() priv_key = load_key('priv') signer = RSARawSigner(private_key_data=priv_key) encrypted = signer.sign(string_to_sign) unsigner = RSAPublicKey.load_pkcs1(pubkey) padded = unsigner.public_decrypt(encrypted) actual = unsigner.unpad_message(padded) self.assertEqual(six.b(hashed), actual, "Expected {}, got {}".format(hashed, actual))
def test_does_not_authenticate_a_false_message(self): """Given an authentic message, we authenticate""" mws_time = int(time.time()) headers = self.generate_headers("GET", "/mauth/v1/mauth.json", "", mws_time) request = mock.Mock(headers=headers, path="/mauth/v2/mauth.json?open=1", method="GET", data="") with mock.patch( "flask_mauth.mauth.authenticators.SecurityTokenCacher") as tok: cacher = tok.return_value cacher.get.return_value = dict( app_name="Apple", app_uuid=self.app_uuid, security_token=dict(public_key_str=load_key('pub')), created_at="2016-11-20 12:08:46 UTC") authenticator = LocalAuthenticator( mauth_auth=mock.Mock(), logger=mock.Mock(), mauth_api_version='v2', mauth_base_url='https://mauth-sandbox.imedidata.net') with self.assertRaises(InauthenticError) as exc: result = authenticator.signature_valid(request) self.assertEqual("Signature verification failed for Mock", str(exc.exception))
def test_authenticates_a_genuine_message_v15(self): """Given an authentic message using pkcs#1.5, we authenticate""" mws_time = int(time.time()) headers = self.generate_headers("GET", "/mauth/v2/mauth.json", "", mws_time, keytype='pkcs15') request = mock.Mock(headers=headers, path="/mauth/v2/mauth.json?open=1", method="GET", data="") with mock.patch( "flask_mauth.mauth.authenticators.SecurityTokenCacher") as tok: cacher = tok.return_value cacher.get.return_value = dict( app_name="Apple", app_uuid=self.app_uuid, security_token=dict(public_key_str=load_key('pub_pkcs15')), created_at="2016-11-20 12:08:46 UTC") authenticator = LocalAuthenticator( mauth_auth=mock.Mock(), logger=mock.Mock(), mauth_api_version='v2', mauth_base_url='https://mauth-sandbox.imedidata.net') result = authenticator.signature_valid(request) self.assertTrue(result)
def generate_headers(self, verb, path, body, mws_time=None, app_uuid=None, keytype='pkcs1'): """ Generates a Signature String :param verb: HTTP verb, eg GET :param path: URL Path (without query strings) :param body: Body of request :param time: :param app_uuid: :return: """ if mws_time is None: mws_time = self.mws_time if app_uuid is None: app_uuid = self.app_uuid key_suffix = "priv" if keytype == 'pkcs15': key_suffix = "priv_pkcs15" signer = requests_mauth.MAuth(app_uuid=app_uuid, private_key_data=load_key(key_suffix)) signature_string, seconds_since_epoch = signer.make_signature_string( verb=verb, url_path=path, body=body, seconds_since_epoch=mws_time) signed_string = signer.signer.sign(signature_string) auth_headers = signer.make_authentication_headers( signed_string, mws_time) return auth_headers
def test_app_configuration_with_valid_call(self): """If the call is authenticated then the call will get passed""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" @self.app.route("/", methods=['GET']) @requires_authentication def test_url_closed(): return "Ping" client = self.app.test_client() with mock.patch("flask_mauth.auth.LocalAuthenticator") as local_auth: m_auth = local_auth.return_value m_auth.is_authentic.return_value = True, 200, "" authenticator = MAuthAuthenticator() authenticator.init_app(self.app) # protected URL rv = client.get("/") self.assertEqual(200, rv.status_code) self.assertEqual(b'Ping', rv.data)
def test_app_configuration_wrong_mode(self): """With incorrect mode, initialisation of app is wrong""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_MODE'] = "banana" with self.assertRaises(TypeError) as exc: authenticator = MAuthAuthenticator(self.app) self.assertEqual(str(exc.exception), "MAuthAuthenticator MAUTH_MODE must be one of local or remote")
def test_app_configuration_missing_base_url(self): """With BASE_URL missing, initialisation of app is wrong""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" with self.assertRaises(TypeError) as exc: authenticator = MAuthAuthenticator(self.app) self.assertEqual(str(exc.exception), "MAuthAuthenticator requires a MAUTH_BASE_URL and MAUTH_VERSION")
def test_app_configuration_missing_key(self): """With Key Text missing, initialisation of app is wrong""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" with self.assertRaises(TypeError) as exc: authenticator = MAuthAuthenticator(self.app) self.assertEqual(str(exc.exception), "MAuthAuthenticator requires both a MAUTH_APP_UUID and MAUTH_KEY_DATA to be set")
def test_app_configuration_remote(self): """With remote mode, initialisation of app is ok""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_MODE'] = "remote" try: authenticator = MAuthAuthenticator(self.app) except TypeError as exc: self.fail("Shouldn't raise an exception") self.assertEqual('remote', authenticator.mauth_mode)
def test_app_configuration(self): """With everything present, initialisation of app is ok""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" try: authenticator = MAuthAuthenticator(self.app) except TypeError as exc: self.fail("Shouldn't raise an exception")
def setUp(self): self.__get_public_key__ = KeyHolder.get_public_key KeyHolder.get_public_key = MagicMock(return_value=load_key("rsapub")) Config.V2_ONLY_AUTHENTICATE = False self.logger = logging.getLogger() self.v1_headers = copy.deepcopy(X_MWS_HEADERS) self.v2_headers = copy.deepcopy(MWSV2_HEADERS) self.signable = RequestSignable(method="POST", url=URL, body=BODY) self.authenticator = LocalAuthenticator( self.signable, Signed.from_headers(self.v1_headers), self.logger)
def test_app_configuration_and_call_open_url(self): """An open route will pass""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" authenticator = MAuthAuthenticator() authenticator.init_app(self.app) @self.app.route("/lemon", methods=['GET']) def test_url_open(): return "Ping" client = self.app.test_client() # open URL rv = client.get("/lemon") self.assertEqual(200, rv.status_code) self.assertEqual(b'Ping', rv.data)
def test_app_configuration_and_call_protected_url(self): """A protected route will raise if the call is inauthentic""" key_text = load_key('priv') self.app.config['MAUTH_APP_UUID'] = '671785CD-15CE-458A-9779-8132C8F60F04' self.app.config['MAUTH_KEY_DATA'] = key_text self.app.config['MAUTH_BASE_URL'] = "https://mauth-sandbox.imedidata.net" self.app.config['MAUTH_VERSION'] = "v2" self.app.config['MAUTH_MODE'] = "local" authenticator = MAuthAuthenticator() authenticator.init_app(self.app) @self.app.route("/", methods=['GET']) @requires_authentication def test_url_closed(): return "Ping" client = self.app.test_client() # protected URL rv = client.get("/") self.assertEqual(401, rv.status_code) self.assertEqual(dict(errors=dict(mauth=["Authentication Failed. No mAuth signature present; " "X-MWS-Authentication header is blank."])), json.loads(rv.data.decode('utf-8')))
def setUp(self): self.app_uuid = 'b0603e5c-c344-488e-83ba-9290ea8dc17d' self.public_key = load_key()
def test_authentication_v2_happy_path_pub_key(self): self.authenticator.signed = Signed.from_headers(self.v2_headers) KeyHolder.get_public_key = MagicMock(return_value=load_key("pub")) self.assertTrue(self.authenticator._authenticate())
def test_authentication_v1_happy_path_pub_key(self): KeyHolder.get_public_key = MagicMock(return_value=load_key("pub")) self.assertTrue(self.authenticator._authenticate())