mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 15:08:06 +08:00
fix(mcp): catch JSONDecodeError in OAuth discovery functions 🤖🤖🤖 (#34868)
This commit is contained in:
@ -146,7 +146,7 @@ def discover_protected_resource_metadata(
|
||||
return ProtectedResourceMetadata.model_validate(response.json())
|
||||
elif response.status_code == 404:
|
||||
continue # Try next URL
|
||||
except (RequestError, ValidationError):
|
||||
except (RequestError, ValidationError, json.JSONDecodeError):
|
||||
continue # Try next URL
|
||||
|
||||
return None
|
||||
@ -166,7 +166,7 @@ def discover_oauth_authorization_server_metadata(
|
||||
return OAuthMetadata.model_validate(response.json())
|
||||
elif response.status_code == 404:
|
||||
continue # Try next URL
|
||||
except (RequestError, ValidationError):
|
||||
except (RequestError, ValidationError, json.JSONDecodeError):
|
||||
continue # Try next URL
|
||||
|
||||
return None
|
||||
@ -276,7 +276,7 @@ def check_support_resource_discovery(server_url: str) -> tuple[bool, str]:
|
||||
else:
|
||||
return False, ""
|
||||
return False, ""
|
||||
except RequestError:
|
||||
except (RequestError, json.JSONDecodeError, IndexError):
|
||||
# Not support resource discovery, fall back to well-known OAuth metadata
|
||||
return False, ""
|
||||
|
||||
|
||||
@ -862,6 +862,15 @@ class TestAuthOrchestration:
|
||||
result = discover_protected_resource_metadata(None, "https://api.example.com")
|
||||
assert result is None
|
||||
|
||||
# JSONDecodeError (non-JSON 200 response)
|
||||
mock_get.side_effect = None
|
||||
bad_json_response = Mock()
|
||||
bad_json_response.status_code = 200
|
||||
bad_json_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
|
||||
mock_get.return_value = bad_json_response
|
||||
result = discover_protected_resource_metadata(None, "https://api.example.com")
|
||||
assert result is None
|
||||
|
||||
@patch("core.helper.ssrf_proxy.get")
|
||||
def test_discover_oauth_authorization_server_metadata(self, mock_get):
|
||||
# Success
|
||||
@ -892,6 +901,14 @@ class TestAuthOrchestration:
|
||||
result = discover_oauth_authorization_server_metadata(None, "https://api.example.com")
|
||||
assert result is None
|
||||
|
||||
# JSONDecodeError (non-JSON 200 response)
|
||||
bad_json_response = Mock()
|
||||
bad_json_response.status_code = 200
|
||||
bad_json_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
|
||||
mock_get.return_value = bad_json_response
|
||||
result = discover_oauth_authorization_server_metadata(None, "https://api.example.com")
|
||||
assert result is None
|
||||
|
||||
def test_get_effective_scope(self):
|
||||
prm = ProtectedResourceMetadata(
|
||||
resource="https://api.example.com",
|
||||
@ -997,6 +1014,24 @@ class TestAuthOrchestration:
|
||||
supported, url = check_support_resource_discovery("https://api")
|
||||
assert supported is False
|
||||
|
||||
# Case 6: JSONDecodeError (non-JSON 200 response)
|
||||
mock_get.side_effect = None
|
||||
bad_json_res = Mock()
|
||||
bad_json_res.status_code = 200
|
||||
bad_json_res.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
|
||||
mock_get.return_value = bad_json_res
|
||||
supported, url = check_support_resource_discovery("https://api")
|
||||
assert supported is False
|
||||
assert url == ""
|
||||
|
||||
# Case 7: Empty authorization_servers array (IndexError)
|
||||
empty_res = Mock()
|
||||
empty_res.status_code = 200
|
||||
empty_res.json.return_value = {"authorization_servers": []}
|
||||
mock_get.return_value = empty_res
|
||||
supported, url = check_support_resource_discovery("https://api")
|
||||
assert supported is False
|
||||
|
||||
def test_discover_oauth_metadata(self):
|
||||
with patch("core.mcp.auth.auth_flow.discover_protected_resource_metadata") as mock_prm:
|
||||
with patch("core.mcp.auth.auth_flow.discover_oauth_authorization_server_metadata") as mock_asm:
|
||||
|
||||
Reference in New Issue
Block a user