def test_verify_ok(self): partial_test_claims = dict(email='*****@*****.**', issued_at=time()) test_jwt = AuthResponseHelper.generate_test_jwt(**partial_test_claims) test_claims = AuthResponseHelper.generate_test_claims( **partial_test_claims) with AuthResponseHelper(): authenticator = Authenticator() result = authenticator.verify_jwt(test_jwt) self.assertEqual(test_claims, result)
def test_verify_raises_error_while_decoding_with_verification(self): partial_test_claims = dict( email='*****@*****.**', issued_at=time() - 120) # this is to force the token to expire. test_jwt = AuthResponseHelper.generate_test_jwt(**partial_test_claims) with self.assertRaises(InvalidTokenError): with AuthResponseHelper(): authenticator = Authenticator() authenticator.verify_jwt(test_jwt)
def test_unified_endpoint_check_status_on_running_job_ok(self): test_jwt_ttl = config.cart_export_min_access_token_ttl + 10 mock_user_id = 'user1' mock_jwt_subject = 'fake|' + mock_user_id mock_cart_uuid = 'mock-cart-1234' expected_export_token = 'abc123' mock_job = dict( status='RUNNING', user_id=mock_jwt_subject, final=False, last_update=dict(state=dict(collection_uuid='ci-123', collection_version='cv-123'))) export_url = f'{self.base_url}/resources/carts/{mock_cart_uuid}/export?token={expected_export_token}' # NOTE The empty side_effect is to ensure that "initiate" never get called. with patch.object(CartExportJobManager, 'initiate', side_effect=[]): with patch.object(CartExportJobManager, 'get', side_effect=[mock_job]): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt( '*****@*****.**', identifier=mock_user_id, ttl=test_jwt_ttl) response = requests.get( export_url, headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(301, response.status_code) self.assertEqual(export_url, response.headers['Location']) self.assertEqual('10', response.headers['Retry-After'])
def test_unified_fetch_endpoint_initiate_ok(self): test_jwt_ttl = config.cart_export_min_access_token_ttl + 10 mock_user_id = 'user1' mock_jwt_subject = 'fake|' + mock_user_id mock_cart_uuid = 'mock-cart-1234' expected_export_token = 'abc123' mock_job = dict( status='RUNNING', user_id=mock_jwt_subject, final=False, last_update=dict(state=dict(collection_uuid='ci-123', collection_version='cv-123'))) export_url = f'{self.base_url}/fetch/resources/carts/{mock_cart_uuid}/export' with patch.object(CartExportJobManager, 'initiate', side_effect=[expected_export_token]): with patch.object(CartExportJobManager, 'get', side_effect=[mock_job]): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt( '*****@*****.**', identifier=mock_user_id, ttl=test_jwt_ttl) response = requests.post( export_url, headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(200, response.status_code) response_body = response.json() self.assertEqual(301, response_body['Status']) self.assertEqual(f'{export_url}?token={expected_export_token}', response_body['Location'])
def test_authenticate_via_fusillade_ok(self): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt('*****@*****.**') response = requests.get(f'{self.base_url}/auth', headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(200, response.status_code)
def test_access_info_blocks_access_due_to_server_error(self): claims = { "iss": f'http://{self.server_thread.address[0]}:12345/' # This issuer is inaccessible. } problematic_jwt = jwt_encode(claims, None, None).decode() with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/me', headers=dict(Authorization=f'Bearer {problematic_jwt}')) self.assertEqual(403, response.status_code)
def test_get_public_keys(self): public_key = TestKeyManager.get_public_key() exponent = public_key.public_numbers().e modulus = public_key.public_numbers().n with AuthResponseHelper(): authenticator = Authenticator() key_map = authenticator.get_public_keys(config.access_token_issuer) self.assertIn('local_test', key_map) test_key = key_map['local_test'] self.assertEqual(exponent, test_key.public_numbers().e) self.assertEqual(modulus, test_key.public_numbers().n)
def test_access_info_ok(self): test_email = '*****@*****.**' test_group = 'hca' with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt(test_email, group=test_group) response = requests.get(f'{self.base_url}/me', headers=dict(Authorization=f'Bearer {test_jwt}')) self.assertEqual(200, response.status_code) response_data = response.json() self.assertTrue(0 < response_data['ttl'] <= 60) response_claims = response_data['claims'] self.assertEqual(test_email, response_claims['https://auth.data.humancellatlas.org/email']) self.assertEqual(test_group, response_claims['https://auth.data.humancellatlas.org/group'])
def test_handle_callback_from_fusillade_ok(self): payload = dict(access_token='abc', id_token='def', expires_in=1234, decoded_token='{"foo": "bar"}', state='') expected_response = dict(access_token='abc', id_token='def', expires_in='1234', decoded_token=dict(foo='bar'), state='') with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/auth/callback', payload) self.assertEqual(200, response.status_code) self.assertEqual(expected_response, {k: v for k, v in response.json().items() if k != 'login_url'})
def test_unified_endpoint_initiate_returns_http_400_due_to_soon_to_be_expiring_token( self): test_jwt_ttl = 10 mock_cart_uuid = 'mock-cart-1234' expected_export_token = 'abc123' export_url = f'{self.base_url}/resources/carts/{mock_cart_uuid}/export' with patch.object(CartExportJobManager, 'initiate', side_effect=[expected_export_token]): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt('*****@*****.**', ttl=test_jwt_ttl) response = requests.post( export_url, headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(400, response.status_code)
def test_unified_endpoint_check_status_with_invalid_token_responed_with_http_400( self): test_jwt_ttl = config.cart_export_min_access_token_ttl + 10 mock_user_id = 'user1' mock_cart_uuid = 'mock-cart-1234' expected_export_token = 'abc123' export_url = f'{self.base_url}/resources/carts/{mock_cart_uuid}/export?token={expected_export_token}' # NOTE The empty side_effect is to ensure that "initiate" never get called. with patch.object(CartExportJobManager, 'initiate', side_effect=[]): with patch.object(CartExportJobManager, 'get', side_effect=[InvalidExecutionTokenError()]): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt( '*****@*****.**', identifier=mock_user_id, ttl=test_jwt_ttl) response = requests.get( export_url, headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(400, response.status_code)
def test_unified_fetch_endpoint_check_status_on_succeeded_job_ok(self): test_jwt_ttl = config.cart_export_min_access_token_ttl + 10 mock_user_id = 'user1' mock_jwt_subject = 'fake|' + mock_user_id mock_cart_uuid = 'mock-cart-1234' expected_export_token = 'abc123' mock_collection_uuid = 'ci-123' mock_collection_ver = 'cv-123' mock_job = dict( status='SUCCEEDED', user_id=mock_jwt_subject, final=True, last_update=dict( state=dict(collection_uuid=mock_collection_uuid, collection_version=mock_collection_ver))) export_url = f'{self.base_url}/fetch/resources/carts/{mock_cart_uuid}/export?token={expected_export_token}' # NOTE The empty side_effect is to ensure that "initiate" never get called. with patch.object(CartExportJobManager, 'initiate', side_effect=[]): with patch.object(CartExportJobManager, 'get', side_effect=[mock_job]): with AuthResponseHelper(self.base_url) as helper: test_jwt = helper.generate_test_jwt( '*****@*****.**', identifier=mock_user_id, ttl=test_jwt_ttl) response = requests.get( export_url, headers=dict(Authorization=f'Bearer {test_jwt}'), allow_redirects=False) self.assertEqual(200, response.status_code) response_body = response.json() self.assertEqual(200, response_body['Status']) prefix_expected_url = CollectionDataAccess.endpoint_url( 'collections', mock_collection_uuid) self.assertEqual( f'{prefix_expected_url}?version={mock_collection_ver}&replica=aws', response_body['Location'])
def test_handle_callback_from_fusillade_without_some_payload(self): payload = dict(id_token='def') with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/auth/callback', payload) self.assertEqual(400, response.status_code)
def test_access_info_blocks_access_with_invalid_jwt(self): invalid_jwt = jwt_encode({'foo': 'bar'}, None, None).decode() with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/me', headers=dict(Authorization=f'Bearer {invalid_jwt}')) self.assertEqual(403, response.status_code)
def test_access_info_blocks_access_without_jwt(self): with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/me') self.assertEqual(401, response.status_code)
def test_authenticate_via_fusillade_redirects_to_fusillade(self): with AuthResponseHelper(self.base_url): response = requests.get(f'{self.base_url}/auth', allow_redirects=False) self.assertEqual(302, response.status_code) self.assertRegex(response.headers['Location'], r'^https://auth(\.[a-z]+|)\.data\.humancellatlas.org/')