@@ -3765,7 +3765,28 @@ async def prepare_rust_mcp_tool_execution(
37653765 if not gateway_url :
37663766 return {"eligible" : False , "fallbackReason" : "missing-gateway-url" }
37673767
3768- if has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
3768+ # Per-user personal credentials always take priority over
3769+ # gateway-level OAuth tokens.
3770+ user_credential_headers = None
3771+ if has_gateway and app_user_email and gateway_id_str :
3772+ try :
3773+ from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
3774+
3775+ with fresh_db_session () as cred_db :
3776+ cred_service = CredentialStorageService (cred_db )
3777+ cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
3778+ if cred_record :
3779+ cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
3780+ if cred_value :
3781+ user_credential_headers = CredentialStorageService .build_auth_headers (
3782+ cred_record .credential_type , cred_value , gateway_auth_type
3783+ )
3784+ except Exception as e :
3785+ logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
3786+
3787+ if user_credential_headers :
3788+ headers = user_credential_headers
3789+ elif has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
37693790 grant_type = gateway_oauth_config .get ("grant_type" , "client_credentials" )
37703791 if grant_type == "authorization_code" :
37713792 try :
@@ -3793,28 +3814,8 @@ async def prepare_rust_mcp_tool_execution(
37933814 logger .error (f"Failed to obtain OAuth access token for gateway { gateway_name } : { e } " )
37943815 raise ToolInvocationError (f"OAuth authentication failed for gateway: { str (e )} " )
37953816 else :
3796- # Check for per-user personal credentials before falling back to shared gateway auth
3797- user_credential_headers = None
3798- if has_gateway and app_user_email and gateway_id_str :
3799- try :
3800- from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
3801-
3802- with fresh_db_session () as cred_db :
3803- cred_service = CredentialStorageService (cred_db )
3804- cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
3805- if cred_record :
3806- cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
3807- if cred_value :
3808- user_credential_headers = CredentialStorageService .build_auth_headers (
3809- cred_record .credential_type , cred_value , gateway_auth_type
3810- )
3811- except Exception as e :
3812- logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
3813-
3814- if user_credential_headers :
3815- headers = user_credential_headers
3816- else :
3817- headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
3817+ # No per-user credentials and no OAuth — fall back to shared gateway auth
3818+ headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
38183819
38193820 if request_headers :
38203821 headers = compute_passthrough_headers_cached (
@@ -4867,7 +4868,28 @@ async def invoke_tool(
48674868
48684869 # Handle OAuth authentication for the gateway (using local variables)
48694870 # NOTE: Use has_gateway instead of gateway to avoid accessing detached ORM object
4870- if has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
4871+ # Per-user personal credentials always take priority over
4872+ # gateway-level OAuth tokens.
4873+ user_credential_headers = None
4874+ if has_gateway and app_user_email and gateway_id_str :
4875+ try :
4876+ from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
4877+
4878+ with fresh_db_session () as cred_db :
4879+ cred_service = CredentialStorageService (cred_db )
4880+ cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
4881+ if cred_record :
4882+ cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
4883+ if cred_value :
4884+ user_credential_headers = CredentialStorageService .build_auth_headers (
4885+ cred_record .credential_type , cred_value , gateway_auth_type
4886+ )
4887+ except Exception as e :
4888+ logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
4889+
4890+ if user_credential_headers :
4891+ headers = user_credential_headers
4892+ elif has_gateway and gateway_auth_type == "oauth" and isinstance (gateway_oauth_config , dict ) and gateway_oauth_config :
48714893 grant_type = gateway_oauth_config .get ("grant_type" , "client_credentials" )
48724894
48734895 if grant_type == "authorization_code" :
@@ -4903,28 +4925,8 @@ async def invoke_tool(
49034925 logger .error (f"Failed to obtain OAuth access token for gateway { gateway_name } : { e } " )
49044926 raise ToolInvocationError (f"OAuth authentication failed for gateway: { str (e )} " )
49054927 else :
4906- # Check for per-user personal credentials before falling back to shared gateway auth
4907- user_credential_headers = None
4908- if has_gateway and app_user_email and gateway_id_str :
4909- try :
4910- from mcpgateway .services .credential_storage_service import CredentialStorageService # pylint: disable=import-outside-toplevel
4911-
4912- with fresh_db_session () as cred_db :
4913- cred_service = CredentialStorageService (cred_db )
4914- cred_record = await cred_service .get_credential_record (gateway_id_str , app_user_email )
4915- if cred_record :
4916- cred_value = await cred_service .get_credential (gateway_id_str , app_user_email )
4917- if cred_value :
4918- user_credential_headers = CredentialStorageService .build_auth_headers (
4919- cred_record .credential_type , cred_value , gateway_auth_type
4920- )
4921- except Exception as e :
4922- logger .debug (f"Failed to check personal credentials for gateway { gateway_name } : { e } " )
4923-
4924- if user_credential_headers :
4925- headers = user_credential_headers
4926- else :
4927- headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
4928+ # No per-user credentials and no OAuth — fall back to shared gateway auth
4929+ headers = decode_auth (gateway_auth_value ) if gateway_auth_value else {}
49284930
49294931 # Use cached passthrough headers (no DB query needed)
49304932 if request_headers :
0 commit comments