@@ -3761,7 +3761,28 @@ async def prepare_rust_mcp_tool_execution(
37613761 if not gateway_url :
37623762 return {"eligible" : False , "fallbackReason" : "missing-gateway-url" }
37633763
3764- if has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
3764+ # Per-user personal credentials always take priority over
3765+ # gateway-level OAuth tokens.
3766+ user_credential_headers = None
3767+ if has_gateway and app_user_email and gateway_id_str :
3768+ try :
3769+ from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
3770+
3771+ with fresh_db_session () as cred_db :
3772+ cred_service = CredentialStorageService (cred_db )
3773+ cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
3774+ if cred_record :
3775+ cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
3776+ if cred_value :
3777+ user_credential_headers = CredentialStorageService .build_auth_headers (
3778+ cred_record .credential_type , cred_value , gateway_auth_type
3779+ )
3780+ except Exception as e :
3781+ logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
3782+
3783+ if user_credential_headers :
3784+ headers = user_credential_headers
3785+ elif has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
37653786 grant_type = gateway_oauth_config .get ("grant_type" , "client_credentials" )
37663787 if grant_type == "authorization_code" :
37673788 try :
@@ -3789,28 +3810,8 @@ async def prepare_rust_mcp_tool_execution(
37893810 logger .error (f"Failed to obtain OAuth access token for gateway { gateway_name } : { e } " )
37903811 raise ToolInvocationError (f"OAuth authentication failed for gateway: { str (e )} " )
37913812 else :
3792- # Check for per-user personal credentials before falling back to shared gateway auth
3793- user_credential_headers = None
3794- if has_gateway and app_user_email and gateway_id_str :
3795- try :
3796- from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
3797-
3798- with fresh_db_session () as cred_db :
3799- cred_service = CredentialStorageService (cred_db )
3800- cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
3801- if cred_record :
3802- cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
3803- if cred_value :
3804- user_credential_headers = CredentialStorageService .build_auth_headers (
3805- cred_record .credential_type , cred_value , gateway_auth_type
3806- )
3807- except Exception as e :
3808- logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
3809-
3810- if user_credential_headers :
3811- headers = user_credential_headers
3812- else :
3813- headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
3813+ # No per-user credentials and no OAuth — fall back to shared gateway auth
3814+ headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
38143815
38153816 if request_headers :
38163817 headers = compute_passthrough_headers_cached (
@@ -4862,7 +4863,28 @@ async def invoke_tool(
48624863
48634864 # Handle OAuth authentication for the gateway (using local variables)
48644865 # NOTE: Use has_gateway instead of gateway to avoid accessing detached ORM object
4865- if has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
4866+ # Per-user personal credentials always take priority over
4867+ # gateway-level OAuth tokens.
4868+ user_credential_headers = None
4869+ if has_gateway and app_user_email and gateway_id_str :
4870+ try :
4871+ from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
4872+
4873+ with fresh_db_session () as cred_db :
4874+ cred_service = CredentialStorageService (cred_db )
4875+ cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
4876+ if cred_record :
4877+ cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
4878+ if cred_value :
4879+ user_credential_headers = CredentialStorageService .build_auth_headers (
4880+ cred_record .credential_type , cred_value , gateway_auth_type
4881+ )
4882+ except Exception as e :
4883+ logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
4884+
4885+ if user_credential_headers :
4886+ headers = user_credential_headers
4887+ elif has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
48664888 grant_type = gateway_oauth_config .get ("grant_type" , "client_credentials" )
48674889
48684890 if grant_type == "authorization_code" :
@@ -4898,28 +4920,8 @@ async def invoke_tool(
48984920 logger .error (f"Failed to obtain OAuth access token for gateway { gateway_name } : { e } " )
48994921 raise ToolInvocationError (f"OAuth authentication failed for gateway: { str (e )} " )
49004922 else :
4901- # Check for per-user personal credentials before falling back to shared gateway auth
4902- user_credential_headers = None
4903- if has_gateway and app_user_email and gateway_id_str :
4904- try :
4905- from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
4906-
4907- with fresh_db_session () as cred_db :
4908- cred_service = CredentialStorageService (cred_db )
4909- cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
4910- if cred_record :
4911- cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
4912- if cred_value :
4913- user_credential_headers = CredentialStorageService .build_auth_headers (
4914- cred_record .credential_type , cred_value , gateway_auth_type
4915- )
4916- except Exception as e :
4917- logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
4918-
4919- if user_credential_headers :
4920- headers = user_credential_headers
4921- else :
4922- headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
4923+ # No per-user credentials and no OAuth — fall back to shared gateway auth
4924+ headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
49234925
49244926 # Use cached passthrough headers (no DB query needed)
49254927 if request_headers :
0 commit comments