diff --git a/http_client/src/vonage_http_client/auth.py b/http_client/src/vonage_http_client/auth.py index 9c9fc641..c1125a44 100644 --- a/http_client/src/vonage_http_client/auth.py +++ b/http_client/src/vonage_http_client/auth.py @@ -37,10 +37,10 @@ def __init__( application_id: Optional[str] = None, private_key: Optional[str] = None, signature_secret: Optional[str] = None, - signature_method: Optional[Literal['md5', 'sha1', 'sha256', 'sha512']] = None, + signature_method: Optional[Literal['md5', 'sha1', 'sha256', 'sha512']] = 'md5', ) -> None: self._validate_input_combinations( - api_key, api_secret, application_id, private_key + api_key, api_secret, application_id, private_key, signature_secret ) self._api_key = api_key @@ -110,18 +110,27 @@ def sign_params(self, params: dict) -> dict: if self._signature_method is None: hasher.update(self._signature_secret.encode()) - return hasher.hexdigest() + def check_signature(self, params) -> bool: + params = dict(params) + signature = params.pop('sig', '').lower() + return hmac.compare_digest(signature, self.signature(params)) + def _validate_input_combinations( - self, api_key, api_secret, application_id, private_key + self, api_key, api_secret, application_id, private_key, signature_secret ): - if (api_key and not api_secret) or (not api_key and api_secret): + if (api_secret or signature_secret) and not api_key: + raise InvalidAuthError( + '`api_key` must be set when `api_secret` or `signature_secret` is set.' + ) + + if api_key and not (api_secret or signature_secret): raise InvalidAuthError( - 'Both api_key and api_secret must be set or both must be None.' + 'At least one of `api_secret` and `signature_secret` must be set if `api_key` is set.' ) if (application_id and not private_key) or (not application_id and private_key): raise InvalidAuthError( - 'Both application_id and private_key must be set or both must be None.' + 'Both `application_id` and `private_key` must be set or both must be None.' ) diff --git a/http_client/src/vonage_http_client/http_client.py b/http_client/src/vonage_http_client/http_client.py index 8a5d3d58..66c85807 100644 --- a/http_client/src/vonage_http_client/http_client.py +++ b/http_client/src/vonage_http_client/http_client.py @@ -136,6 +136,10 @@ def make_request( self._headers['Authorization'] = self._auth.create_basic_auth_string() elif auth_type == 'signature': params = self._auth.sign_params(params) + + print(params) + print(self._auth.check_signature(params)) + with self._session.request( request_type, url, @@ -161,6 +165,7 @@ def _parse_response(self, response: Response) -> Union[dict, None]: logger.debug( f'Response received from {response.url} with status code: {response.status_code}; headers: {response.headers}' ) + print(response.request.headers) content_type = response.headers['Content-Type'].split(';', 1)[0] if 200 <= response.status_code < 300: if response.status_code == 204: diff --git a/http_client/tests/test_auth.py b/http_client/tests/test_auth.py index be805604..4303b469 100644 --- a/http_client/tests/test_auth.py +++ b/http_client/tests/test_auth.py @@ -19,6 +19,8 @@ def read_file(path): api_secret = '1234qwerasdfzxcv' application_id = 'asdfzxcv' private_key = read_file('data/dummy_private_key.txt') +signature_secret = 'signature_secret' +signature_method = 'sha256' def test_create_auth_class_and_get_objects(): @@ -27,6 +29,8 @@ def test_create_auth_class_and_get_objects(): api_secret=api_secret, application_id=application_id, private_key=private_key, + signature_secret=signature_secret, + signature_method=signature_method, ) assert auth.api_key == api_key diff --git a/http_client/tests/test_http_client.py b/http_client/tests/test_http_client.py index 94bcbf99..11483336 100644 --- a/http_client/tests/test_http_client.py +++ b/http_client/tests/test_http_client.py @@ -95,6 +95,33 @@ def test_make_post_request(): assert loads(responses.calls[0].request.body) == params +@responses.activate +def test_make_post_request_with_signature(): + build_response( + path, 'POST', 'https://example.com/post_signed_params', 'example_post.json' + ) + client = HttpClient( + Auth( + api_key='asdfzxcv', signature_secret='qwerasdfzxcv', signature_method='sha256' + ), + http_client_options={'api_host': 'example.com'}, + ) + params = { + 'test': 'post request', + 'testing': 'http client', + } + + res = client.post( + host='example.com', + request_path='/post_signed_params', + params=params, + auth_type='signature', + ) + assert res['hello'] == 'world!' + + assert loads(responses.calls[0].request.body) == params + + @responses.activate def test_http_response_general_error(): build_response(path, 'GET', 'https://example.com/get_json', '400.json', 400)