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 == str(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: 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_should_return_403_when_token_is_expired(client, sample_api_key): with freeze_time('2001-01-01T12:00:00'): token = __create_token(sample_api_key.service_id) with freeze_time('2001-01-01T12:00:40'): with pytest.raises(AuthError) as exc: request.headers = {'Authorization': 'Bearer {}'.format(token)} requires_auth() assert exc.value.short_message == 'Error: Your system clock must be accurate to within 30 seconds' assert exc.value.service_id == str(sample_api_key.service_id) assert str(exc.value.api_key_id) == str(sample_api_key.id)
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: requires_auth() assert exc.value.short_message == 'Invalid token: service has no API keys' assert exc.value.service_id == str(sample_service.id)
def test_auth_should_not_allow_request_with_non_hs256_algorithm( client, sample_api_key): iss = str(sample_api_key.service_id) # code copied from notifications_python_client.authentication.py::create_jwt_token headers = {"typ": 'JWT', "alg": 'HS512'} claims = {'iss': iss, 'iat': int(time.time())} token = jwt.encode(payload=claims, key=str(uuid.uuid4()), headers=headers) request.headers = {'Authorization': 'Bearer {}'.format(token)} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message == 'Invalid token: algorithm used is not HS256'
def test_auth_should_not_allow_request_with_invalid_iat( client, sample_api_key, is_admin): iss = str( sample_api_key.service_id ) if not is_admin else current_app.config["ADMIN_CLIENT_USER_NAME"] # code copied from notifications_python_client.authentication.py::create_jwt_token headers = {"typ": "JWT", "alg": "HS256"} claims = {"iss": iss, "iat": "not an integer"} token = jwt.encode(payload=claims, key=str(uuid.uuid4()), headers=headers) request.headers = {"Authorization": f"Bearer {token}"} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message.startswith("Invalid token:")
def test_auth_should_not_allow_request_with_no_iat(client, sample_api_key): iss = str(sample_api_key.service_id) # code copied from notifications_python_client.authentication.py::create_jwt_token headers = {"typ": "JWT", "alg": "HS256"} claims = { "iss": iss # 'iat': not provided } token = jwt.encode(payload=claims, key=str(uuid.uuid4()), headers=headers) request.headers = {"Authorization": "Bearer {}".format(token)} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message == "Invalid token: signature, api token not found"
def test_auth_should_not_allow_request_with_extra_claims( client, sample_api_key): iss = str(sample_api_key.service_id) key = get_unsigned_secrets(sample_api_key.service_id)[0] headers = {"typ": 'JWT', "alg": 'HS256'} claims = { 'iss': iss, 'iat': int(time.time()), 'aud': 'notifications.service.gov.uk' # extra claim that we don't support } token = jwt.encode(payload=claims, key=key, headers=headers) request.headers = {'Authorization': 'Bearer {}'.format(token)} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message == GENERAL_TOKEN_ERROR_MESSAGE
def test_should_return_403_when_token_is_expired( client, sample_api_key, mocker, ): mock_logger = mocker.patch( "app.authentication.auth.current_app.logger.info") with freeze_time("2001-01-01T12:00:00"): token = __create_token(sample_api_key.service_id) with freeze_time("2001-01-01T12:00:40"): with pytest.raises(AuthError) as exc: request.headers = {"Authorization": "Bearer {}".format(token)} requires_auth() assert exc.value.short_message == "Error: Your system clock must be accurate to within 30 seconds" assert exc.value.service_id == sample_api_key.service_id assert exc.value.api_key_id == sample_api_key.id mock_logger.assert_called_with( "JWT: iat value was 978350400 while server clock is 978350440")
def required_authentication(): no_auth_req = [ url_for("status.show_status"), url_for("notifications.process_ses_response"), url_for("notifications.process_firetext_response"), url_for("notifications.process_mmg_response"), url_for("status.show_delivery_status"), url_for("spec.get_spec"), ] if request.path not in no_auth_req: from app.authentication import auth error = auth.requires_auth() if error: return error
def required_authentication(): if request.path != url_for('status.show_status'): from app.authentication import auth error = auth.requires_auth() if error: return error