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 c414aae59d89b8347a53a75aa0f0d4310b6da798..2edd3fea398fa393a5d84dd6adc0700f44a518e9 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 1906c2a5d63731453ab6d92b9e0f28f7edc97d10..0a304f64d5ba10b8383d8920d5bf90c08eeefd0c 100644
--- a/gso/settings.py
+++ b/gso/settings.py
@@ -167,6 +167,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 e10c8b7f415f22cfdc0348ea42b445ba198f3f35..7fd75ed90ce883cee989be5aadd1179a08309982 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 bd2ea9876dfd943ea089257be71f41dd7985ec51..7caff457fcbd923a586b28d9dfce6c926be6bd10 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 92f71d6df5d7c8dde4f34fdb04925857f27e7512..c3e697e866af6fdef0082a6467b149adf3fed193 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -224,10 +224,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 e9164c69a1c47d6ccd52d42bcd97b8a22b8bf994..52cc31bbe6332dee82d14ae69cec3931271317e4 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 6339e95aebecdd751059d9fe88bd83a02f7afdd0..0cbf5617073bd41345f9e6b7ed7897bff3a2b0f5 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 febe770feca4ad00b96e3af2f7e46e6f70b1547f..e091b890ed5e4182666107c23c8ec9ee850423ea 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
 
@@ -262,7 +268,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
 
@@ -275,7 +281,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})
     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 35afaf9b3eb5e669a641989027d1a4d47c35e273..99490f77795bcf7bfb0a89afc2d1bce63e3f680e 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -133,10 +133,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"]