def test_should_allow_valid_token_for_request_with_path_params_for_admin_url_with_second_secret(client): with set_config(client.application, 'API_INTERNAL_SECRETS', ["secret1", "secret2"]): token = create_jwt_token( current_app.config['API_INTERNAL_SECRETS'][0], current_app.config['ADMIN_CLIENT_USER_NAME'] ) response = client.get('/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200 token = create_jwt_token( current_app.config['API_INTERNAL_SECRETS'][1], current_app.config['ADMIN_CLIENT_USER_NAME'] ) response = client.get('/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_should_persist_notification(notify_api, sample_template, sample_email_template, template_type, fake_uuid, mocker): with notify_api.test_request_context(), notify_api.test_client() as client: mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type)) mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) template = sample_template if template_type == 'sms' else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == 'sms' \ else sample_email_template.service.created_by.email_address data = { 'to': to, 'template': template.id } api_key = ApiKey( service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) mocked.assert_called_once_with([fake_uuid], queue='send-{}'.format(template_type)) assert response.status_code == 201 notification = notifications_dao.get_notification_by_id(fake_uuid) assert notification.to == to assert notification.template_id == template.id assert notification.notification_type == template_type
def test_should_send_email_to_anyone_with_test_key( notify_api, sample_email_template, mocker, restricted, limit, fake_uuid ): with notify_api.test_request_context(), notify_api.test_client() as client: mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) data = { 'to': '*****@*****.**', 'template': sample_email_template.id } sample_email_template.service.restricted = restricted sample_email_template.service.message_limit = limit api_key = ApiKey( service=sample_email_template.service, name='test_key', created_by=sample_email_template.created_by, key_type=KEY_TYPE_TEST ) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/email', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))] ) app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with([fake_uuid], queue='research-mode') assert response.status_code == 201
def test_should_delete_notification_and_return_error_if_sqs_fails( client, sample_email_template, sample_template, fake_uuid, mocker, template_type, queue_name): mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type), side_effect=Exception("failed to talk to SQS")) mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) template = sample_template if template_type == SMS_TYPE else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \ else sample_email_template.service.created_by.email_address data = {'to': to, 'template': template.id} api_key = ApiKey(service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) with pytest.raises(Exception) as e: client.post(path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header)) ]) assert str(e.value) == 'failed to talk to SQS' mocked.assert_called_once_with([fake_uuid], queue=queue_name) assert not notifications_dao.get_notification_by_id(fake_uuid) assert not NotificationHistory.query.get(fake_uuid)
def test_should_send_sms_if_team_api_key_and_a_service_user( client, sample_template, fake_uuid, mocker): mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) data = { 'to': sample_template.service.created_by.mobile_number, 'template': sample_template.id } api_key = ApiKey(service=sample_template.service, name='team_key', created_by=sample_template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/sms', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with( [fake_uuid], queue='send-sms-tasks') assert response.status_code == 201
def test_should_persist_notification(client, sample_template, sample_email_template, fake_uuid, mocker, template_type, queue_name): mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type)) mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) template = sample_template if template_type == SMS_TYPE else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \ else sample_email_template.service.created_by.email_address data = {'to': to, 'template': template.id} api_key = ApiKey(service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) mocked.assert_called_once_with([fake_uuid], queue=queue_name) assert response.status_code == 201 notification = notifications_dao.get_notification_by_id(fake_uuid) assert notification.to == to assert notification.template_id == template.id assert notification.notification_type == template_type
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].secret else: service = dao_fetch_service_by_id(service_id) data = { "service": service, "name": uuid.uuid4(), "created_by": service.created_by, "key_type": key_type, } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.secret else: client_id = current_app.config["ADMIN_CLIENT_USER_NAME"] secret = current_app.config["ADMIN_CLIENT_SECRET"] token = create_jwt_token(secret=secret, client_id=client_id) return "Authorization", "Bearer {}".format(token)
def test_should_send_email_to_anyone_with_test_key(client, sample_email_template, mocker, restricted, limit, fake_uuid): mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) data = { 'to': '*****@*****.**', 'template': sample_email_template.id } sample_email_template.service.restricted = restricted sample_email_template.service.message_limit = limit api_key = ApiKey(service=sample_email_template.service, name='test_key', created_by=sample_email_template.created_by, key_type=KEY_TYPE_TEST) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/email', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with( [fake_uuid], queue='research-mode-tasks') assert response.status_code == 201
def test_should_accept_token_that_just_within_bounds_old(): # make token 31 seconds ago with freeze_time('2001-01-01T12:00:00'): token = create_jwt_token("key", "client_id") with freeze_time('2001-01-01T12:00:30'): assert decode_jwt_token(token, "key")
def test_proxy_key_on_admin_auth_endpoint(notify_api, check_proxy_header, header_value, expected_status): token = create_jwt_token( current_app.config["ADMIN_CLIENT_SECRET"], current_app.config["ADMIN_CLIENT_USER_NAME"], ) with set_config_values( notify_api, { "ROUTE_SECRET_KEY_1": "key_1", "ROUTE_SECRET_KEY_2": "", "CHECK_PROXY_HEADER": check_proxy_header, }, ): with notify_api.test_client() as client: response = client.get( path="/service", headers=[ ("X-Custom-Forwarder", header_value), ("Authorization", "Bearer {}".format(token)), ], ) assert response.status_code == expected_status
def test_should_allow_valid_token_for_request_with_path_params_for_admin_url( client): token = create_jwt_token(current_app.config['ADMIN_CLIENT_SECRET'], current_app.config['ADMIN_CLIENT_USER_NAME']) response = client.get('/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_authentication_returns_token_expired_when_service_uses_expired_key_and_has_multiple_keys( client, sample_api_key): expired_key = { "service": sample_api_key.service, "name": "expired_key", "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, } expired_api_key = ApiKey(**expired_key) save_model_api_key(expired_api_key) another_key = { "service": sample_api_key.service, "name": "another_key", "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( secret=get_unsigned_secret(expired_api_key.id), client_id=str(sample_api_key.service_id), ) expire_api_key(service_id=sample_api_key.service_id, api_key_id=expired_api_key.id) request.headers = {"Authorization": "Bearer {}".format(token)} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message == "Invalid token: API key revoked" assert exc.value.service_id == expired_api_key.service_id assert exc.value.api_key_id == expired_api_key.id
def test_authentication_returns_token_expired_when_service_uses_expired_key_and_has_multiple_keys( client, sample_api_key): expired_key = { 'service': sample_api_key.service, 'name': 'expired_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } expired_api_key = ApiKey(**expired_key) save_model_api_key(expired_api_key) another_key = { 'service': sample_api_key.service, 'name': 'another_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token(secret=get_unsigned_secret(expired_api_key.id), client_id=str(sample_api_key.service_id)) expire_api_key(service_id=sample_api_key.service_id, api_key_id=expired_api_key.id) request.headers = {'Authorization': 'Bearer {}'.format(token)} with pytest.raises(AuthError) as exc: validate_service_api_key_auth() assert exc.value.short_message == 'Invalid token: API key revoked' assert exc.value.service_id == expired_api_key.service_id assert exc.value.api_key_id == expired_api_key.id
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].secret else: service = dao_fetch_service_by_id(service_id) data = { 'service': service, 'name': uuid.uuid4(), 'created_by': service.created_by, 'key_type': key_type } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.secret else: client_id = current_app.config['ADMIN_CLIENT_USER_NAME'] secret = current_app.config['ADMIN_CLIENT_SECRET'] token = create_jwt_token(secret=secret, client_id=client_id) return 'Authorization', 'Bearer {}'.format(token)
def test_should_accept_token_that_is_just_within_bounds_future(): # make token 30 seconds in the future with freeze_time('2001-01-01T12:00:30'): token = create_jwt_token("key", "client_id") with freeze_time('2001-01-01T12:00:00'): assert decode_jwt_token(token, "key")
def test_authentication_passes_when_service_has_multiple_keys_some_expired( client, sample_api_key): expired_key_data = {'service': sample_api_key.service, 'name': 'expired_key', 'expiry_date': datetime.utcnow(), 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } expired_key = ApiKey(**expired_key_data) save_model_api_key(expired_key) another_key = {'service': sample_api_key.service, 'name': 'another_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( secret=get_unsigned_secret(api_key.id), client_id=str(sample_api_key.service_id)) response = client.get( '/notifications', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_should_not_allow_invalid_secret(client, sample_api_key): token = create_jwt_token(secret="not-so-secret", client_id=str(sample_api_key.service_id)) response = client.get('/notifications', headers={'Authorization': "Bearer {}".format(token)}) assert response.status_code == 403 data = json.loads(response.get_data()) assert data['message'] == {"token": ['Invalid token: API key not found']}
def test_token_should_contain_correct_claim_keys(): token = create_jwt_token("key", "client_id") decoded = decode_token(token, "key") assert 'iss' in decoded assert "client_id" == decoded['iss'] assert 'iat' in decoded assert 'req' not in decoded assert 'pay' not in decoded
def test_token_should_contain_correct_claim_keys(): token = create_jwt_token("key", "client_id") decoded = decode_token(token, "key") assert 'iss' in decoded assert "client_id" == decoded['iss'] assert 'iat' in decoded assert 'req' not in decoded assert 'pay' not in decoded
def test_should_reject_token_that_is_just_out_of_bounds_future(): # make token 31 seconds ago with freeze_time('2001-01-01T12:00:31'): token = create_jwt_token("key", "client_id") with freeze_time('2001-01-01T12:00:00'), pytest.raises(TokenExpiredError) as e: decode_jwt_token(token, "key") assert e.value.token['iss'] == "client_id"
def test_decode_jwt_token_raises_token_error_if_jwt_invalid_token_error_exception( decode_mock, exception_class): token = create_jwt_token("key", "client_id") decode_mock.side_effect = exception_class with pytest.raises(TokenError) as err: decode_jwt_token(token, "key") assert str(err.value.message) == TOKEN_ERROR_DEFAULT_ERROR_MESSAGE
def test_authentication_returns_error_when_service_inactive(client, sample_api_key): sample_api_key.service.active = False token = create_jwt_token(secret=str(sample_api_key.id), client_id=str(sample_api_key.service_id)) response = client.get('/notifications', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 403 error_message = json.loads(response.get_data()) assert error_message['message'] == {'token': ['Invalid token: service is archived']}
def test_should_not_allow_invalid_secret(client, sample_api_key): token = create_jwt_token(secret="not-so-secret", client_id=str(sample_api_key.service_id)) response = client.get("/notifications", headers={"Authorization": "Bearer {}".format(token)}) assert response.status_code == 403 data = json.loads(response.get_data()) assert data["message"] == { "token": ["Invalid token: signature, api token not found"] }
def test_authentication_returns_error_when_service_has_no_secrets( client, sample_service, fake_uuid): token = create_jwt_token(secret=fake_uuid, client_id=str(sample_service.id)) request.headers = {'Authorization': 'Bearer {}'.format(token)} with pytest.raises(AuthError) as exc: validate_service_api_key_auth() assert exc.value.short_message == 'Invalid token: service has no API keys' assert exc.value.service_id == sample_service.id
def test_should_not_allow_service_id_that_is_not_the_wrong_data_type(client, sample_api_key): token = create_jwt_token(secret=get_unsigned_secrets(sample_api_key.service_id)[0], client_id=str('not-a-valid-id')) response = client.get( '/notifications', headers={'Authorization': "Bearer {}".format(token)} ) assert response.status_code == 403 data = json.loads(response.get_data()) assert data['message'] == {"token": ['Invalid token: service id is not the right data type']}
def test_should_reject_token_that_is_just_out_of_bounds_future(): # make token 31 seconds ago with freeze_time('2001-01-01T12:00:31'): token = create_jwt_token("key", "client_id") with freeze_time('2001-01-01T12:00:00'), pytest.raises( TokenExpiredError) as e: decode_jwt_token(token, "key") assert e.value.token['iss'] == "client_id"
def test_should_reject_token_that_is_too_old(): # make token 31 seconds ago with freeze_time('2001-01-01T12:00:00'): token = create_jwt_token("key", "client_id") with freeze_time('2001-01-01T12:00:31'), pytest.raises( TokenExpiredError) as e: decode_jwt_token(token, "key") assert "Token has expired. See our requirements" in e.value.message assert e.value.token['iss'] == "client_id"
def test_authentication_returns_error_when_admin_client_has_no_secrets(client): api_secret = current_app.config.get('API_INTERNAL_SECRETS')[0] api_service_id = current_app.config.get('ADMIN_CLIENT_USER_NAME') token = create_jwt_token(secret=api_secret, client_id=api_service_id) with set_config(client.application, 'API_INTERNAL_SECRETS', []): response = client.get( '/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 401 error_message = json.loads(response.get_data()) assert error_message['message'] == { "token": ["Unauthorized: admin authentication token not found"] }
def request(self, method, url, data=None, params=None): logger.debug("API request {} {}".format(method, url)) payload = json.dumps(data) api_token = create_jwt_token( self.api_key, self.service_id ) headers = { "Content-type": "application/json", "Authorization": "Bearer {}".format(api_token), "User-agent": "NOTIFY-API-PYTHON-CLIENT/{}".format(__version__), } url = urlparse.urljoin(self.base_url, url) start_time = monotonic() try: response = requests.request( method, url, headers=headers, data=payload, params=params ) response.raise_for_status() except requests.RequestException as e: api_error = HTTPError.create(e) logger.error( "API {} request on {} failed with {} '{}'".format( method, url, api_error.status_code, api_error.message ) ) raise api_error finally: elapsed_time = monotonic() - start_time logger.debug("API {} request on {} finished in {}".format(method, url, elapsed_time)) try: if response.status_code == 204: return return response.json() except ValueError: raise InvalidResponse( response, message="No JSON response object could be decoded" )
def test_authentication_returns_error_when_admin_client_has_no_secrets(client): api_secret = current_app.config.get('ADMIN_CLIENT_SECRET') api_service_id = current_app.config.get('ADMIN_CLIENT_USER_NAME') token = create_jwt_token(secret=api_secret, client_id=api_service_id) with set_config(client.application, 'ADMIN_CLIENT_SECRET', ''): response = client.get( '/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 403 error_message = json.loads(response.get_data()) assert error_message['message'] == { "token": ["Invalid token: signature, api token is not valid"] }
def test_get_token_issuer_should_handle_invalid_token_with_no_iss(): token = create_jwt_token("key", "client_id") token = jwt.encode(payload={'iat': 1234}, key='1234', headers={ 'typ': 'JWT', 'alg': 'HS256' }) with pytest.raises(TokenIssuerError) as e: get_token_issuer(token) assert "Invalid token: iss field not provided. See our requirements" in e.value.message
def test_authentication_returns_error_when_service_doesnt_exit( client, sample_api_key): # get service ID and secret the wrong way around token = create_jwt_token(secret=str(sample_api_key.service_id), client_id=str(sample_api_key.id)) response = client.get('/notifications', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 403 error_message = json.loads(response.get_data()) assert error_message['message'] == { 'token': ['Invalid token: service not found'] }
def test_accepts_admin_jwt(self, client, db_session, required_permission): @requires_admin_auth_or_user_in_service( required_permission=required_permission) def endpoint_that_requires_admin_auth_or_permission_for_service(): pass token = create_jwt_token(current_app.config['ADMIN_CLIENT_SECRET'], current_app.config['ADMIN_CLIENT_USER_NAME']) request.view_args['service_id'] = 'some-service-id' request.headers = {'Authorization': 'Bearer {}'.format(token)} endpoint_that_requires_admin_auth_or_permission_for_service()
def test_get_token_issuer_should_handle_invalid_token_with_no_iss(): token = create_jwt_token("key", "client_id") token = jwt.encode(payload={ 'iat': 1234 }, key='1234', headers={ 'typ': 'JWT', 'alg': 'HS256' }).decode() with pytest.raises(TokenIssuerError): get_token_issuer(token)
def test_authentication_returns_error_when_admin_client_secret_is_invalid(client): api_secret = current_app.config.get('API_INTERNAL_SECRETS')[0] token = create_jwt_token( secret=api_secret, client_id=current_app.config.get('ADMIN_CLIENT_USER_NAME') ) current_app.config['API_INTERNAL_SECRETS'][0] = 'something-wrong' response = client.get( '/service', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 401 error_message = json.loads(response.get_data()) assert error_message['message'] == {"token": ["Unauthorized: admin authentication token not found"]} current_app.config['API_INTERNAL_SECRETS'][0] = api_secret
def test_authentication_returns_error_when_admin_client_secret_is_invalid( client): api_secret = current_app.config.get("ADMIN_CLIENT_SECRET") token = create_jwt_token( secret=api_secret, client_id=current_app.config.get("ADMIN_CLIENT_USER_NAME")) current_app.config["ADMIN_CLIENT_SECRET"] = "something-wrong" response = client.get("/service", headers={"Authorization": "Bearer {}".format(token)}) assert response.status_code == 403 error_message = json.loads(response.get_data()) assert error_message["message"] == { "token": ["Invalid token: signature, api token is not valid"] } current_app.config["ADMIN_CLIENT_SECRET"] = api_secret
def test_should_send_notification_to_whitelist_recipient( client, notify_db, notify_db_session, notification_type, to, _create_sample_template, key_type, service_restricted, mocker ): service = create_sample_service(notify_db, notify_db_session, limit=2, restricted=service_restricted) apply_async = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(notification_type)) template = _create_sample_template(notify_db, notify_db_session, service=service) if notification_type == 'sms': service_whitelist = create_sample_service_whitelist(notify_db, notify_db_session, service=service, mobile_number=to) elif notification_type == 'email': service_whitelist = create_sample_service_whitelist(notify_db, notify_db_session, service=service, email_address=to) assert service_whitelist.service_id == service.id assert to in [member.recipient for member in service.whitelist] create_sample_notification(notify_db, notify_db_session, template=template, service=service) data = { 'to': to, 'template': str(template.id) } sample_key = create_sample_api_key(notify_db, notify_db_session, service, key_type=key_type) auth_header = create_jwt_token(secret=sample_key.unsigned_secret, client_id=str(sample_key.service_id)) response = client.post( path='/notifications/{}'.format(notification_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) json_resp = json.loads(response.get_data(as_text=True)) assert response.status_code == 201 assert json_resp['data']['notification']['id'] assert json_resp['data']['body'] == template.content assert json_resp['data']['template_version'] == template.version assert apply_async.called
def test_should_not_send_notification_to_non_whitelist_recipient_in_trial_mode( client, notify_db, notify_db_session, notification_type, to, _create_sample_template, key_type, mocker ): service = create_sample_service(notify_db, notify_db_session, limit=2, restricted=True) service_whitelist = create_sample_service_whitelist(notify_db, notify_db_session, service=service) apply_async = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(notification_type)) template = _create_sample_template(notify_db, notify_db_session, service=service) assert service_whitelist.service_id == service.id assert to not in [member.recipient for member in service.whitelist] create_sample_notification(notify_db, notify_db_session, template=template, service=service) data = { 'to': to, 'template': str(template.id) } api_key = create_sample_api_key(notify_db, notify_db_session, service, key_type=key_type) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/{}'.format(notification_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) expected_response_message = ( 'Can’t send to this recipient when service is in trial mode ' '– see https://www.notifications.service.gov.uk/trial-mode' ) if key_type == KEY_TYPE_NORMAL else ('Can’t send to this recipient using a team-only API key') json_resp = json.loads(response.get_data(as_text=True)) assert response.status_code == 400 assert json_resp['result'] == 'error' assert expected_response_message in json_resp['message']['to'] apply_async.assert_not_called()
def test_should_send_sms_if_team_api_key_and_a_service_user(notify_api, sample_template, fake_uuid, mocker): with notify_api.test_request_context(), notify_api.test_client() as client: mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) data = { 'to': sample_template.service.created_by.mobile_number, 'template': sample_template.id } api_key = ApiKey(service=sample_template.service, name='team_key', created_by=sample_template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/sms', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with([fake_uuid], queue='send-sms') assert response.status_code == 201
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].unsigned_secret else: service = dao_fetch_service_by_id(service_id) data = { 'service': service, 'name': uuid.uuid4(), 'created_by': service.created_by, 'key_type': key_type } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.unsigned_secret else: client_id = current_app.config.get('ADMIN_CLIENT_USER_NAME') secret = current_app.config.get('ADMIN_CLIENT_SECRET') token = create_jwt_token(secret=secret, client_id=client_id) return 'Authorization', 'Bearer {}'.format(token)
def test_should_return_issuer_from_token(): token = create_jwt_token("key", "client_id") issuer = get_token_issuer(token) assert issuer == "client_id"
def test_should_reject_token_request_if_missing_client_id(): with pytest.raises(AssertionError) as err: create_jwt_token("key", None) assert str(err.value) == "Missing client id"
def _create_auth_header_from_key(api_key): token = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) return [('Authorization', 'Bearer {}'.format(token))]
def test_token_should_contain_correct_headers(): token = create_jwt_token("key", "client_id") headers = jwt.get_unverified_header(token) assert headers['typ'] == 'JWT' assert headers['alg'] == 'HS256'
def test_token_should_fail_to_decode_if_wrong_key(): token = create_jwt_token("key", "client_id") with pytest.raises(jwt.DecodeError) as err: decode_token(token, "wrong key") assert str(err.value) == "Signature verification failed"
def test_token_should_contain_correct_issued_at_claim(): token = create_jwt_token("key", "client_id") decoded = decode_token(token, "key") assert decoded['iat'] == calendar.timegm(time.gmtime())
def test_should_reject_token_with_invalid_key(): token = create_jwt_token("key", "client_id") with pytest.raises(TokenDecodeError) as e: decode_jwt_token(token=token, secret="wrong-key") assert e.value.message == "Invalid token"
def test_should_reject_token_request_if_missing_secret(): with pytest.raises(AssertionError) as err: create_jwt_token(secret=None, client_id="client_id") assert str(err.value) == "Missing secret key"