diff --git a/gso/__init__.py b/gso/__init__.py
index c0dd125738c7eec85455683a17e4d24757eefccd..c5dbc6b0f14c3e9ecc89e8615a6bae66ae384aa4 100644
--- a/gso/__init__.py
+++ b/gso/__init__.py
@@ -10,8 +10,7 @@ import gso.products
 import gso.workflows  # noqa: F401
 from gso.api import router as api_router
 from gso.auth.oidc import oidc_instance
-from gso.auth.opa import opa_instance
-from gso.middlewares import ModifyProcessEndpointResponse
+from gso.auth.opa import graphql_opa_instance, opa_instance
 from gso.graphql_api.types import GSO_SCALAR_OVERRIDES
 
 SCALAR_OVERRIDES.update(GSO_SCALAR_OVERRIDES)
@@ -22,6 +21,7 @@ def init_gso_app() -> OrchestratorCore:
     app = OrchestratorCore(base_settings=app_settings)
     app.register_authentication(oidc_instance)
     app.register_authorization(opa_instance)
+    app.register_graphql_authorization(graphql_opa_instance)
     app.register_graphql()
     app.include_router(api_router, prefix="/api")
     return app
diff --git a/gso/api/v1/imports.py b/gso/api/v1/imports.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/gso/api/v1/processes.py b/gso/api/v1/processes.py
index 7664486a7bb8f9863505e378c59125e3c94f1ac0..f4977ed463835b8cb5f8fc54edc32f3675cabb13 100644
--- a/gso/api/v1/processes.py
+++ b/gso/api/v1/processes.py
@@ -8,7 +8,6 @@ from orchestrator.db import ProcessStepTable
 from orchestrator.schemas.base import OrchestratorBaseModel
 from orchestrator.security import authorize
 
-
 router = APIRouter(prefix="/processes", tags=["Processes"], dependencies=[Depends(authorize)])
 
 
diff --git a/gso/auth/oidc.py b/gso/auth/oidc.py
index a1a9547c17966a755c3fe6cc840058c1fd4be09f..d9acb24534d894242cf0946d5d57087ee014d1bf 100644
--- a/gso/auth/oidc.py
+++ b/gso/auth/oidc.py
@@ -1,17 +1,11 @@
-"""OpenID Connect and Open Policy Agent Integration for GSO Application.
-
-This module provides helper functions and classes for handling OpenID Connect (OIDC) and
-Open Policy Agent (OPA) related functionalities within the GSO application. It includes
-implementations for OIDC-based user authentication and user information modeling. Additionally,
-it facilitates making authorization decisions based on policies defined in OPA. Key components
-comprise OIDCUser, OIDCUserModel, OPAResult, and opa_decision. These elements integrate with
-FastAPI to ensure secure API development.
-"""
+"""Module contains the OIDC Authentication class."""
 
 import re
+from collections.abc import Callable
 from functools import wraps
 from http import HTTPStatus
 from json import JSONDecodeError
+from typing import Any
 
 from fastapi.exceptions import HTTPException
 from fastapi.requests import Request
@@ -28,14 +22,19 @@ _CALLBACK_STEP_API_URL_PATTERN = re.compile(
 )
 
 
+def _is_client_credentials_token(intercepted_token: dict) -> bool:
+    return "sub" not in intercepted_token
+
 def _is_callback_step_endpoint(request: Request) -> bool:
     """Check if the request is a callback step API call."""
     return re.match(_CALLBACK_STEP_API_URL_PATTERN, request.url.path) is not None
 
 
-def ensure_openid_config_loaded(func):
+def ensure_openid_config_loaded(func: Callable) -> Callable:
+    """Ensure that the openid_config is loaded before calling the function."""
+
     @wraps(func)
-    async def wrapper(self, async_request: AsyncClient, *args, **kwargs):
+    async def wrapper(self: OIDCAuth, async_request: AsyncClient, *args: Any, **kwargs: Any) -> dict:
         await self.check_openid_config(async_request)
         return await func(self, async_request, *args, **kwargs)
 
@@ -49,15 +48,9 @@ class OIDCAuthentication(OIDCAuth):
         1. Validate the Credentials at :term: `AAI` proxy by calling the UserInfo endpoint
     """
 
-    _instance = None
-
-    def __new__(cls, *args, **kwargs):
-        if cls._instance is None:
-            cls._instance = super(OIDCAuthentication, cls).__new__(cls)
-        return cls._instance
-
     @staticmethod
     async def is_bypassable_request(request: Request) -> bool:
+        """Check if the request is a callback step API call."""
         return _is_callback_step_endpoint(request=request)
 
     @ensure_openid_config_loaded
@@ -69,7 +62,12 @@ class OIDCAuthentication(OIDCAuth):
         :return: OIDCUserModel: OIDC user model from openid server
 
         """
-        await self.introspect_token(async_request, token)
+        intercepted_token = await self.introspect_token(async_request, token)
+        client_id = intercepted_token.get("client_id")
+        if _is_client_credentials_token(intercepted_token):
+            return OIDCUserModel(
+                client_id=client_id
+            )
 
         response = await async_request.post(
             self.openid_config.userinfo_endpoint,
@@ -97,6 +95,8 @@ class OIDCAuthentication(OIDCAuth):
             )
             raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail=response.text)
 
+        data["client_id"] = client_id
+
         return OIDCUserModel(data)
 
     @ensure_openid_config_loaded
diff --git a/gso/auth/oidc_policy_helper.py b/gso/auth/oidc_policy_helper.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/gso/auth/opa.py b/gso/auth/opa.py
index 88c8edfb9a795de1ee535bd364ce59f47b90fa91..9d801a8b958b7283f23aca3ac12a530451e85d62 100644
--- a/gso/auth/opa.py
+++ b/gso/auth/opa.py
@@ -1,41 +1,49 @@
+"""Module contains the OPA authorization class that is used to get decisions from the OPA server."""
+
 from http import HTTPStatus
 
 from fastapi.exceptions import HTTPException
-from fastapi.params import Depends
 from httpx import AsyncClient, NetworkError
-from oauth2_lib.fastapi import OIDCUserModel, OPAAuthorization, OPAResult
+from oauth2_lib.fastapi import GraphQLOPAAuthorization, OPAAuthorization, OPAResult
 from oauth2_lib.settings import oauth2lib_settings
-from starlette.requests import Request
 from structlog import get_logger
 
-from gso.auth.oidc import oidc_instance
-
 logger = get_logger(__name__)
 
 
-class OPAAuthorization(OPAAuthorization):
-    _instance = None
+async def _get_decision(opa_url: str, async_request: AsyncClient, opa_input: dict) -> OPAResult:
+    logger.debug("Posting input json to Policy agent", opa_url=opa_url, input=opa_input)
+    try:
+        result = await async_request.post(opa_url, json=opa_input)
+    except (NetworkError, TypeError) as exc:
+        logger.debug("Could not get decision from policy agent", error=str(exc))
+        raise HTTPException(status_code=HTTPStatus.SERVICE_UNAVAILABLE, detail="Policy agent is unavailable") from exc
+
+    json_result = result.json()
+    logger.debug("Received decision from policy agent", decision=json_result)
 
-    def __new__(cls, *args, **kwargs):
-        if cls._instance is None:
-            cls._instance = super(OPAAuthorization, cls).__new__(cls)
-        return cls._instance
+    return OPAResult(decision_id=json_result["decision_id"], result=json_result["result"]["allow"])
+
+
+class OPAAuthZ(OPAAuthorization):
+    """Applies OPA decisions to HTTP requests for authorization."""
 
     async def get_decision(self, async_request: AsyncClient, opa_input: dict) -> OPAResult:
-        logger.debug("Posting input json to Policy agent", opa_url=self.opa_url, input=opa_input)
-        try:
-            result = await async_request.post(self.opa_url, json=opa_input)
-        except (NetworkError, TypeError) as exc:
-            logger.debug("Could not get decision from policy agent", error=str(exc))
-            raise HTTPException(status_code=HTTPStatus.SERVICE_UNAVAILABLE, detail="Policy agent is unavailable")
+        """Get the decision from the OPA server."""
+        return await _get_decision(self.opa_url, async_request, opa_input)
 
-        json_result = result.json()
-        logger.debug("Received decision from policy agent", decision=json_result)
-        return OPAResult(decision_id=json_result["decision_id"], result=json_result["result"]["allow"])
 
+class GraphQLOPAAuthZ(GraphQLOPAAuthorization):
+    """Specializes OPA authorization for GraphQL operations."""
 
-opa_instance = OPAAuthorization(
+    async def get_decision(self, async_request: AsyncClient, opa_input: dict) -> OPAResult:
+        """Get the decision from the OPA server."""
+        return await _get_decision(self.opa_url, async_request, opa_input)
+
+
+opa_instance = OPAAuthZ(
+    opa_url=oauth2lib_settings.OPA_URL,
+)
+graphql_opa_instance = GraphQLOPAAuthZ(
     opa_url=oauth2lib_settings.OPA_URL,
 )
-
-# TODO - Think about Inventoryo-provider since it is not defined in the code but is used in the old branch
\ No newline at end of file
diff --git a/gso/monkeypatches.py b/gso/monkeypatches.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/gso/services/infoblox.py b/gso/services/infoblox.py
index d340ce979f14a8c4d767f0f0e9ccf10331174387..9fc668cd11f6df1ef9d2f796f9242ef3a7ea1309 100644
--- a/gso/services/infoblox.py
+++ b/gso/services/infoblox.py
@@ -37,7 +37,7 @@ def _setup_connection() -> tuple[connector.Connector, IPAMParams]:
     return connector.Connector(options), oss
 
 
-def _allocate_network(  # noqa: PLR0917
+def _allocate_network(
     conn: connector.Connector,
     dns_view: str,
     network_view: str,
diff --git a/gso/settings.py b/gso/settings.py
index fcacd37691ec358c48db59313b7f97332dd4941d..79182702b7eab55c06dca563a90df5c152606bc6 100644
--- a/gso/settings.py
+++ b/gso/settings.py
@@ -173,6 +173,7 @@ class SharepointParams(BaseSettings):
 
 class AuthParams(BaseSettings):
     """Parameters for the authentication service."""
+
     opa_url: str
 
 
diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index b6072c1c6bae54d2d6af93abdba533655902957c..e75660820d72179e03948a402cc9f6a1a636a83a 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -10,17 +10,19 @@ ALL_ALIVE_STATES: list[str] = [
     SubscriptionLifecycle.ACTIVE,
 ]
 
-WF_USABLE_MAP.update({
-    "redeploy_base_config": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
-    "update_ibgp_mesh": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
-    "activate_router": [SubscriptionLifecycle.PROVISIONING],
-    "deploy_twamp": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
-    "modify_trunk_interface": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
-    "activate_iptrunk": [SubscriptionLifecycle.PROVISIONING],
-    "terminate_site": ALL_ALIVE_STATES,
-    "terminate_router": ALL_ALIVE_STATES,
-    "terminate_iptrunk": ALL_ALIVE_STATES,
-})
+WF_USABLE_MAP.update(
+    {
+        "redeploy_base_config": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
+        "update_ibgp_mesh": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
+        "activate_router": [SubscriptionLifecycle.PROVISIONING],
+        "deploy_twamp": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
+        "modify_trunk_interface": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
+        "activate_iptrunk": [SubscriptionLifecycle.PROVISIONING],
+        "terminate_site": ALL_ALIVE_STATES,
+        "terminate_router": ALL_ALIVE_STATES,
+        "terminate_iptrunk": ALL_ALIVE_STATES,
+    }
+)
 
 #  IP trunk workflows
 LazyWorkflowInstance("gso.workflows.iptrunk.activate_iptrunk", "activate_iptrunk")
diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index 9b0e6b87a8a095073875721e79d72c9e03baa66d..0e5a2564039ef3ff1893cf054fed4e62534fdb8f 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -123,10 +123,12 @@ def initialize_subscription(
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
         )
-    side_names = sorted([
-        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
-        subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
-    ])
+    side_names = sorted(
+        [
+            subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
+            subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
+        ]
+    )
     subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{geant_s_sid}"
     return {"subscription": subscription}
 
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index d64331720fcb85cccc829f58d6d3d8b437e55b77..4c7efae913b39938e6f404f71327ab728ff22161 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -229,10 +229,12 @@ def modify_iptrunk_subscription(
             IptrunkInterfaceBlock.new(subscription_id=uuid4(), **member),
         )
 
-    side_names = sorted([
-        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
-        subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
-    ])
+    side_names = sorted(
+        [
+            subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
+            subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
+        ]
+    )
     subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{geant_s_sid}"
 
     return {
diff --git a/requirements.txt b/requirements.txt
index a430ae38c707028526b4e36a0735110ec0b44157..9c8e28c3a21f6db906c1cccb4c8dc792fdb846bc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-orchestrator-core==2.1.2
+orchestrator-core==2.3.0rc3
 requests==2.31.0
 infoblox-client~=0.6.0
 pycountry==23.12.11
diff --git a/setup.py b/setup.py
index 6f52af7f665438ed81928fa4b245d5ec220166b6..169f80789183f482c50491e3bc5f1a391a211e75 100644
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@ setup(
     url="https://gitlab.software.geant.org/goat/gap/geant-service-orchestrator",
     packages=find_packages(),
     install_requires=[
-        "orchestrator-core==2.2.1",
+        "orchestrator-core==2.3.0rc3",
         "requests==2.31.0",
         "infoblox-client~=0.6.0",
         "pycountry==23.12.11",
diff --git a/test/auth/test_oidc_policy_helper.py b/test/auth/test_oidc_policy_helper.py
index 4152e1d016b1599de51d749f825479914d78e2bd..9aa313b43035b55a4daba9d85b28c8eb2b607b96 100644
--- a/test/auth/test_oidc_policy_helper.py
+++ b/test/auth/test_oidc_policy_helper.py
@@ -6,8 +6,14 @@ from fastapi import HTTPException, Request
 from httpx import AsyncClient, NetworkError, Response
 
 from gso.auth.oidc import (
+    OIDCAuthentication,
     OIDCConfig,
-    OIDCAuthentication, OIDCUserModel, OPAResult, opa_decision, _get_decision, _evaluate_decision, _is_callback_step_endpoint,
+    OIDCUserModel,
+    OPAResult,
+    _evaluate_decision,
+    _get_decision,
+    _is_callback_step_endpoint,
+    opa_decision,
 )
 from gso.auth.settings import oauth2lib_settings
 
@@ -275,7 +281,7 @@ async def test_oidc_user_call_no_token(oidc_user, mock_request):
         mock_post.return_value = MagicMock(status_code=200, json=lambda: {"active": False})
         mock_get.return_value = MagicMock(status_code=200, json=dict)
 
-        result = await oidc_user.__call__(mock_request)  # noqa: PLC2801
+        result = await oidc_user.__call__(mock_request)
 
     assert result is None
 
@@ -288,7 +294,7 @@ async def test_oidc_user_call_token_from_request(oidc_user, mock_request, mock_a
     oidc_user.introspect_token = AsyncMock(return_value={"active": True, "sub": "123"})
     oidc_user.userinfo = AsyncMock(return_value=OIDCUserModel({"sub": "123", "name": "John Doe"}))
 
-    result = await oidc_user.__call__(mock_request)  # noqa: PLC2801
+    result = await oidc_user.__call__(mock_request)
 
     assert isinstance(result, OIDCUserModel)
     assert result["sub"] == "123"
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index de15a7124e0311e4a3127ccc10477fd39a4a02b7..13b7f69b5f18c42314c7bcb196e05a1b25a18643 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -137,10 +137,12 @@ def test_successful_iptrunk_creation_with_standard_lso_result(
     subscription_id = state["subscription_id"]
     subscription = Iptrunk.from_subscription(subscription_id)
 
-    sorted_sides = sorted([
-        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
-        subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
-    ])
+    sorted_sides = sorted(
+        [
+            subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
+            subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
+        ]
+    )
     assert subscription.status == "provisioning"
     assert subscription.description == (
         f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, geant_s_sid:{input_form_wizard_data[0]["geant_s_sid"]}"
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index 2a95cc90fc6428dd19c7e9a2b0a0f77a58ef3a2b..98d41e8fc940e8064b9b2c25d8ed717604929094 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -158,10 +158,12 @@ def test_iptrunk_modify_trunk_interface_success(
     assert mocked_detach_interfaces_from_lag.call_count == num_lag_ifaces  # 1 time per nokia side
 
     # Assert all subscription properties have been updated correctly
-    side_names = sorted([
-        subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
-        subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
-    ])
+    side_names = sorted(
+        [
+            subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
+            subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
+        ]
+    )
     assert subscription.description == f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{new_sid}"
     assert subscription.iptrunk.geant_s_sid == input_form_iptrunk_data[1]["geant_s_sid"]
     assert subscription.iptrunk.iptrunk_description == input_form_iptrunk_data[1]["iptrunk_description"]