Accept connection string logins without validating them

SQL, Tables, and Gremlin logins probed the account before signing in, so a user whose key was wrong or whose account was unreachable was blocked at the connect form. The probe is now gone: the connection string is accepted as-is and any bad key surfaces on the data-plane requests made from inside the explorer.

Removes validateDirectConnectionStringConnectivity, isAuthorizationError, and the connectExplorer.errors.connectFailed string along with their tests.

Also takes documentEndpoint straight from the AccountEndpoint in SQL and Gremlin connection strings instead of rebuilding it from the account name and a hardcoded DNS zone. Tables still derives it, since a Tables connection string only carries the table endpoint.
This commit is contained in:
Asier Isayas
2026-08-19 08:42:35 -07:00
parent b4a8e78fed
commit 2e979a9b65
10 changed files with 39 additions and 251 deletions
+1 -30
View File
@@ -28,16 +28,10 @@ import React from "react";
import { useAADAuth } from "./hooks/useAADAuth";
import { useConfig } from "./hooks/useConfig";
import { App } from "./HostedExplorer";
import {
ConnectExplorer,
fetchEncryptedToken,
validateDirectConnectionStringConnectivity,
} from "./Platform/Hosted/Components/ConnectExplorer";
import { ConnectExplorer, fetchEncryptedToken } from "./Platform/Hosted/Components/ConnectExplorer";
import { fetchAccessData } from "./Platform/Hosted/Helpers/PortalAccessData";
const mockFetchEncryptedToken = fetchEncryptedToken as jest.MockedFunction<typeof fetchEncryptedToken>;
const mockValidateDirectConnectionStringConnectivity =
validateDirectConnectionStringConnectivity as jest.MockedFunction<typeof validateDirectConnectionStringConnectivity>;
(ConnectExplorer as jest.Mock).mockImplementation(() => <div data-testid="connect-explorer" />);
@@ -62,7 +56,6 @@ beforeEach(() => {
(useConfig as jest.Mock).mockReturnValue({});
(fetchAccessData as jest.Mock).mockResolvedValue(undefined);
mockFetchEncryptedToken.mockResolvedValue("encrypted-token");
mockValidateDirectConnectionStringConnectivity.mockResolvedValue(undefined);
});
const dispatchPostMessage = (data: unknown, origin: string) => {
@@ -89,7 +82,6 @@ describe("HostedExplorer tryCosmosDB postMessage handler", () => {
});
expect(mockFetchEncryptedToken).not.toHaveBeenCalled();
expect(mockValidateDirectConnectionStringConnectivity).toHaveBeenCalled();
});
it("accepts a valid Mongo connection string from an allowed origin", async () => {
@@ -138,7 +130,6 @@ describe("HostedExplorer tryCosmosDB postMessage handler", () => {
});
expect(mockFetchEncryptedToken).not.toHaveBeenCalled();
expect(mockValidateDirectConnectionStringConnectivity).toHaveBeenCalled();
});
it("accepts a valid Gremlin connection string from an allowed origin", async () => {
@@ -155,26 +146,6 @@ describe("HostedExplorer tryCosmosDB postMessage handler", () => {
});
expect(mockFetchEncryptedToken).not.toHaveBeenCalled();
expect(mockValidateDirectConnectionStringConnectivity).toHaveBeenCalled();
});
it("does not open Data Explorer when the Cosmos client cannot connect", async () => {
mockValidateDirectConnectionStringConnectivity.mockRejectedValue(new Error("Unable to connect to the account."));
const { container } = render(<App />);
const validConnStr = `AccountEndpoint=https://${FAKE_ACCOUNT_NAME}.documents.azure.com:443/;AccountKey=${FAKE_KEY};`;
await act(async () => {
dispatchPostMessage(
{ type: "tryCosmosDBConnectionString", connectionString: validConnStr },
"https://cosmos.azure.com",
);
await Promise.resolve();
});
expect(mockValidateDirectConnectionStringConnectivity).toHaveBeenCalled();
expect(mockFetchEncryptedToken).not.toHaveBeenCalled();
expect(container.querySelector('[data-test="DataExplorerFrame"]')).toBeNull();
});
it("rejects messages from a disallowed origin", async () => {