def test_returns_400_when_using_api_keys_that_do_not_match(self): url = '/test/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature('abc123==', url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(400, response.status_code) url = '/test/?username=test&{}=app-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature('123==', url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(400, response.status_code)
def test_signature_is_same_with_different_blank_payloads(self): base_url = 'http://www.example.com/' signatures = set([ get_signature(self.private_key, base_url, None), get_signature(self.private_key, base_url, ""), get_signature(self.private_key, base_url, {}), ]) self.assertEqual(1, len(signatures)) # all should be same as the empty string version self.assertEqual(get_signature(self.private_key, base_url, ""), signatures.pop())
def test_get_signature_with_complex_non_unicode_payload(self): base_url = 'http://www.example.com/accounts/user/add/' data = {'coverages': [{'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [{'construction_type': u'', 'irpms': [], 'fire_class': None, 'deductible_code': u'500', 'coverage_amount': '100000', 'territory': None, 'rate_code': u'033', 'year_built': None}], 'rate_code': u'005', 'property_id': '6b86b273ff3', 'packages': [], 'year_built': None, 'coverage_amount': '100000', 'irpms': [], 'deductible_code': u'500', 'territory': None}, {'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [], 'rate_code': u'015', 'property_id': 'd4735e3a265', 'packages': [{'rate_code': u'017', 'irpms': [], 'construction_type': u'', 'deductible_code': u'500', 'fire_class': None, 'rateable_amount': 10000, 'territory': None, 'property_id': '6b86b273ff3'}], 'year_built': None, 'coverage_amount': '100000', 'irpms': [], 'deductible_code': u'500', 'territory': None}, {'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [{'construction_type': u'', 'irpms': [], 'fire_class': None, 'deductible_code': u'500', 'coverage_amount': '100000', 'territory': None, 'rate_code': u'033', 'year_built': None}], 'rate_code': u'002', 'property_id': '4e07408562b', 'packages': [], 'year_built': None, 'coverage_amount': '100000', 'irpms': [u'RCC'], 'deductible_code': u'500', 'territory': None}], 'producer': u'matt.morrison', 'policy_type': u'FM', 'policy': {'effective_date': None, 'path': 'APPS9690', 'apps_key': u'FM', 'discount_a': u'1'}, 'company': 9690, 'agency': None, 'policy_id': 1} #' signature = get_signature(self.private_key, base_url, data) expected_signature = '0WhQvC9ZLTIBsLn_N6cfC25qVmwgfsfFMJYlFEWFj4k=' self.assertEqual(expected_signature, signature)
def check_signature(signature, private_key, full_path, payload): """ Checks signature received and verifies that we are able to re-create it from the private key, path, and payload given. :param signature: Signature received from request. :param private_key: Base 64, url encoded private key. :full_path: Full path of request, including GET query string (excluding host) :payload: The request.POST data if present. None if not. :returns: Boolean of whether signature matched or not. """ if isinstance(private_key, bytes): private_key = private_key.decode("ascii") if isinstance(payload, bytes): payload = payload.decode() url_to_check = _strip_signature_from_url(signature, full_path) computed_signature = apysigner.get_signature(private_key, url_to_check, payload) return constant_time_compare(signature, computed_signature)
def _get_signed_url(self, url, query_data): # Currently limited to kinds of data that are key=value pairs. # Binary data is not supported. url_with_client = self._get_url_with_client(url) payload = query_data and parse_qs(query_data) signature = apysigner.get_signature(self.PRIVATE_KEY, url_with_client, payload) return url_with_client + "&{0}={1}".format(self.SIGNATURE_PARAM_NAME, signature)
def test_get_signature_creates_signature_with_payload_data(self): base_url = 'http://www.example.com/accounts/user/add/' data = {'username': '******', 'first_name': 'Mr. Test'} signature = get_signature(self.private_key, base_url, data) expected_signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' self.assertEqual(expected_signature, signature)
def _build_signed_url(self, url, headers): data = {} if self.should_data_be_sent_on_querystring( ) else self._build_signature_dict_for_content_type(headers) signature = apysigner.get_signature(self.private_key, url, data) signed_url = self._escape_url(url) + "&{}={}".format( constants.SIGNATURE_PARAM_NAME, signature) return signed_url
def test_get_signature_creates_signature_with_payload_data(self): base_url = 'http://www.example.com/accounts/user/add/' data = {'username': '******', 'first_name': 'Mr. Test'} signature = get_signature(self.private_key, base_url, data) expected_signature = 'cKOHRf5TZpTrrAGHPFq9g6jRVZwUD_YgEpjk1nAncLo=' self.assertEqual(expected_signature, signature)
def test_post_multivalue_data_payload_is_valid(self): data = {'username': ['tester', 'billyjean']} client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/?{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url, payload=data) response = self.client.post( '{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), data=data ) self.assertEqual(200, response.status_code)
def test_json_api_payload_is_valid(self): json_string = json.dumps({'our': 'data', 'goes': 'here'}) url = '/test/[email protected]&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url, json_string) response = self.client.post( '{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), json_string, content_type="application/vnd.api+json" ) self.assertEqual(200, response.status_code)
def test_patch_json_api_is_valid(self): data = json.dumps({'username': ['tester', 'billyjean']}) url = '/test/?{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url, payload=data) response = self.client.patch( '{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), data=data, content_type="application/vnd.api+json" ) self.assertEqual(200, response.status_code)
def test_json_payload_is_valid(self): json_string = json.dumps({'our': 'data', 'goes': 'here'}) client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/[email protected]&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url, json_string) response = self.client.post( '{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), json_string, content_type="application/json" ) self.assertEqual(200, response.status_code)
def test_patch_json_api_is_valid(self): data = json.dumps({'username': ['tester', 'billyjean']}) client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/?{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url, payload=data) response = self.client.patch( '{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), data=data, content_type="application/vnd.api+json" ) self.assertEqual(200, response.status_code)
def test_signature_works_when_url_contains_escapsed_spaces(self): url = '/test/a%20b%20c/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_returns_200_view_return_value_when_signature_matches(self): url = '/test/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_request_fails_without_correct_settings(self): with self.assertRaises(ImproperlyConfigured): url = '/test/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature('abc123==', url) self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature))
def _build_signed_url(self, url, raw_data): data = {} if self._is_get_request_with_data(raw_data) else raw_data signature = apysigner.get_signature(self.private_key, url, data) signed_url = url + "&{0}={1}".format(constants.SIGNATURE_PARAM_NAME, signature) return signed_url
def _build_signed_url(self, url, headers): data = {} if self.should_data_be_sent_on_querystring() else self._build_signature_dict_for_content_type(headers) signature = apysigner.get_signature(self.private_key, url, data) signed_url = self._escape_url(url) + "&{}={}".format(constants.SIGNATURE_PARAM_NAME, signature) return signed_url
def test_post_multivalue_data_payload_is_valid(self): data = {'username': ['tester', 'billyjean']} url = '/test/?{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url, payload=data) response = self.client.post('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature), data=data) self.assertEqual(200, response.status_code)
def test_get_signature_signs_request_with_no_payload(self): signature = get_signature(self.private_key, 'http://www.example.com/accounts/?one=1&two=2&two=dos&two=two') expected_signature = 'bm9_IDIQtEElubM5r__M0kDMUfdQ__0ZSI-2Bi6DcRo=' self.assertEqual(expected_signature, signature)
def test_signature_works_when_url_contains_escapsed_spaces(self): client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/a%20b%20c/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_returns_200_view_return_value_when_signature_matches(self): client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_get_signature_with_complex_non_unicode_payload(self): base_url = 'http://www.example.com/accounts/user/add/' data = {'coverages': [{'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [{'construction_type': u'', 'irpms': [], 'fire_class': None, 'deductible_code': u'500', 'coverage_amount': '100000', 'territory': None, 'rate_code': u'033', 'year_built': None}], 'rate_code': u'005', 'property_id': '6b86b273ff3', 'packages': [], 'year_built': None, 'coverage_amount': '100000', 'irpms': [], 'deductible_code': u'500', 'territory': None}, {'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [], 'rate_code': u'015', 'property_id': 'd4735e3a265', 'packages': [{'rate_code': u'017', 'irpms': [], 'construction_type': u'', 'deductible_code': u'500', 'fire_class': None, 'rateable_amount': 10000, 'territory': None, 'property_id': '6b86b273ff3'}], 'year_built': None, 'coverage_amount': '100000', 'irpms': [], 'deductible_code': u'500', 'territory': None}, {'construction_type': u'', 'premium': None, 'fire_class': None, 'optional_coverages': [{'construction_type': u'', 'irpms': [], 'fire_class': None, 'deductible_code': u'500', 'coverage_amount': '100000', 'territory': None, 'rate_code': u'033', 'year_built': None}], 'rate_code': u'002', 'property_id': '4e07408562b', 'packages': [], 'year_built': None, 'coverage_amount': '100000', 'irpms': [u'RCC'], 'deductible_code': u'500', 'territory': None}], 'producer': u'matt.morrison', 'policy_type': u'FM', 'policy': {'effective_date': None, 'path': 'APPS9690', 'apps_key': u'FM', 'discount_a': u'1'}, 'company': 9690, 'agency': None, 'policy_id': 1} signature = get_signature(self.private_key, base_url, data) expected_signature = '0WhQvC9ZLTIBsLn_N6cfC25qVmwgfsfFMJYlFEWFj4k=' self.assertEqual(expected_signature, signature)
def test_get_signature_signs_request_with_no_payload(self): signature = get_signature(self.private_key, 'http://www.example.com/accounts/?one=1&two=2&two=dos&two=two') expected_signature = 'LmE4gGmqmPX8L2YuEWH1YgE5G9Kc3JzK8NzjznFVjV0=' self.assertEqual(expected_signature, signature)
def test_does_not_call_database_per_request(self): url = '/test/?username=test&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url) with self.assertNumQueries(0): response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_calls_create_signature_properly_with_get_data_and_with_an_at_symbol(self): url = '/test/[email protected]&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(TEST_PRIVATE_KEY, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)
def test_calls_create_signature_properly_with_get_data_and_with_an_at_symbol(self): client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/test/[email protected]&{}=apps-testclient'.format(constants.CLIENT_ID_PARAM_NAME) signature = get_signature(client.private_key, url) response = self.client.get('{}&{}={}'.format(url, constants.SIGNATURE_PARAM_NAME, signature)) self.assertEqual(200, response.status_code)