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
Example #7
0
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
Example #14
0
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
Example #17
0
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"
Example #28
0
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"]
    }
Example #31
0
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
Example #40
0
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"
Example #43
0
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"