feat: add default Authorization Bearer header and clean up legacy auth
- Provide "Authorization: Bearer " as default starting header - Remove legacy auth props from components - Centralize migration logic and fix localStorage cleanup - Update tests for new auth architecture
This commit is contained in:
parent
f36c649bb9
commit
e08ce8cee9
7 changed files with 45 additions and 62 deletions
|
|
@ -23,10 +23,6 @@ export default tseslint.config(
|
|||
"warn",
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{ argsIgnorePattern: "^_" },
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -154,7 +154,14 @@ const App = () => {
|
|||
return migrateFromLegacyAuth(legacyToken, legacyHeaderName);
|
||||
}
|
||||
|
||||
return [];
|
||||
// Default to Authorization: Bearer as the most common case
|
||||
return [
|
||||
{
|
||||
name: "Authorization",
|
||||
value: "Bearer ",
|
||||
enabled: true,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const [pendingSampleRequests, setPendingSampleRequests] = useState<
|
||||
|
|
@ -243,8 +250,6 @@ const App = () => {
|
|||
args,
|
||||
sseUrl,
|
||||
env,
|
||||
bearerToken,
|
||||
headerName,
|
||||
customHeaders,
|
||||
oauthClientId,
|
||||
oauthScope,
|
||||
|
|
@ -334,11 +339,19 @@ const App = () => {
|
|||
}, [transportType]);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem("lastBearerToken", bearerToken);
|
||||
if (bearerToken) {
|
||||
localStorage.setItem("lastBearerToken", bearerToken);
|
||||
} else {
|
||||
localStorage.removeItem("lastBearerToken");
|
||||
}
|
||||
}, [bearerToken]);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem("lastHeaderName", headerName);
|
||||
if (headerName) {
|
||||
localStorage.setItem("lastHeaderName", headerName);
|
||||
} else {
|
||||
localStorage.removeItem("lastHeaderName");
|
||||
}
|
||||
}, [headerName]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -858,10 +871,6 @@ const App = () => {
|
|||
setEnv={setEnv}
|
||||
config={config}
|
||||
setConfig={setConfig}
|
||||
bearerToken={bearerToken}
|
||||
setBearerToken={setBearerToken}
|
||||
headerName={headerName}
|
||||
setHeaderName={setHeaderName}
|
||||
customHeaders={customHeaders}
|
||||
setCustomHeaders={setCustomHeaders}
|
||||
oauthClientId={oauthClientId}
|
||||
|
|
|
|||
|
|
@ -53,12 +53,7 @@ interface SidebarProps {
|
|||
setSseUrl: (url: string) => void;
|
||||
env: Record<string, string>;
|
||||
setEnv: (env: Record<string, string>) => void;
|
||||
// Legacy auth props (for backward compatibility)
|
||||
bearerToken: string;
|
||||
setBearerToken: (token: string) => void;
|
||||
headerName?: string;
|
||||
setHeaderName?: (name: string) => void;
|
||||
// New custom headers support
|
||||
// Custom headers support
|
||||
customHeaders: CustomHeadersType;
|
||||
setCustomHeaders: (headers: CustomHeadersType) => void;
|
||||
oauthClientId: string;
|
||||
|
|
@ -86,10 +81,6 @@ const Sidebar = ({
|
|||
setSseUrl,
|
||||
env,
|
||||
setEnv,
|
||||
bearerToken: _bearerToken,
|
||||
setBearerToken: _setBearerToken,
|
||||
headerName: _headerName,
|
||||
setHeaderName: _setHeaderName,
|
||||
customHeaders,
|
||||
setCustomHeaders,
|
||||
oauthClientId,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
render,
|
||||
screen,
|
||||
fireEvent,
|
||||
act,
|
||||
waitFor,
|
||||
} from "@testing-library/react";
|
||||
import { render, screen, fireEvent, act } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
import { describe, it, beforeEach, jest } from "@jest/globals";
|
||||
import Sidebar from "../Sidebar";
|
||||
|
|
@ -54,10 +48,6 @@ describe("Sidebar", () => {
|
|||
setOauthScope: jest.fn(),
|
||||
env: {},
|
||||
setEnv: jest.fn(),
|
||||
bearerToken: "",
|
||||
setBearerToken: jest.fn(),
|
||||
headerName: "",
|
||||
setHeaderName: jest.fn(),
|
||||
customHeaders: [],
|
||||
setCustomHeaders: jest.fn(),
|
||||
onConnect: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -649,9 +649,17 @@ describe("useConnection", () => {
|
|||
});
|
||||
|
||||
test("preserves server Authorization header when proxy auth is configured", async () => {
|
||||
const customHeaders: CustomHeaders = [
|
||||
{
|
||||
name: "Authorization",
|
||||
value: "Bearer server-auth-token",
|
||||
enabled: true,
|
||||
},
|
||||
];
|
||||
|
||||
const propsWithBothAuth = {
|
||||
...defaultProps,
|
||||
bearerToken: "server-auth-token",
|
||||
customHeaders,
|
||||
config: {
|
||||
...DEFAULT_INSPECTOR_CONFIG,
|
||||
MCP_PROXY_AUTH_TOKEN: {
|
||||
|
|
@ -811,14 +819,18 @@ describe("useConnection", () => {
|
|||
expect(headers).not.toHaveProperty("X-Disabled");
|
||||
});
|
||||
|
||||
test("migrates from legacy bearerToken and headerName", async () => {
|
||||
const propsWithLegacyAuth = {
|
||||
test("handles migrated legacy auth via custom headers", async () => {
|
||||
// Simulate what App.tsx would do - migrate legacy auth to custom headers
|
||||
const customHeaders: CustomHeaders = [
|
||||
{ name: "X-Custom-Auth", value: "legacy-token", enabled: true },
|
||||
];
|
||||
|
||||
const propsWithMigratedAuth = {
|
||||
...defaultProps,
|
||||
bearerToken: "legacy-token",
|
||||
headerName: "X-Custom-Auth",
|
||||
customHeaders,
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => useConnection(propsWithLegacyAuth));
|
||||
const { result } = renderHook(() => useConnection(propsWithMigratedAuth));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.connect();
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ import {
|
|||
import { getMCPServerRequestTimeout } from "@/utils/configUtils";
|
||||
import { InspectorConfig } from "../configurationTypes";
|
||||
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
||||
import { CustomHeaders, migrateFromLegacyAuth } from "../types/customHeaders";
|
||||
import { CustomHeaders } from "../types/customHeaders";
|
||||
|
||||
interface UseConnectionOptions {
|
||||
transportType: "stdio" | "sse" | "streamable-http";
|
||||
|
|
@ -65,10 +65,7 @@ interface UseConnectionOptions {
|
|||
args: string;
|
||||
sseUrl: string;
|
||||
env: Record<string, string>;
|
||||
// Legacy auth support (for backward compatibility)
|
||||
bearerToken?: string;
|
||||
headerName?: string;
|
||||
// New custom headers support
|
||||
// Custom headers support
|
||||
customHeaders?: CustomHeaders;
|
||||
oauthClientId?: string;
|
||||
oauthScope?: string;
|
||||
|
|
@ -90,8 +87,6 @@ export function useConnection({
|
|||
args,
|
||||
sseUrl,
|
||||
env,
|
||||
bearerToken,
|
||||
headerName,
|
||||
customHeaders,
|
||||
oauthClientId,
|
||||
oauthScope,
|
||||
|
|
@ -384,16 +379,8 @@ export function useConnection({
|
|||
// Create an auth provider with the current server URL
|
||||
const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
|
||||
|
||||
// Handle custom headers (new approach) or legacy auth (backward compatibility)
|
||||
let finalHeaders: CustomHeaders = [];
|
||||
|
||||
if (customHeaders && customHeaders.length > 0) {
|
||||
// Use new custom headers approach
|
||||
finalHeaders = customHeaders;
|
||||
} else if (bearerToken || headerName) {
|
||||
// Migrate from legacy auth approach
|
||||
finalHeaders = migrateFromLegacyAuth(bearerToken, headerName);
|
||||
}
|
||||
// Use custom headers (migration is handled in App.tsx)
|
||||
let finalHeaders: CustomHeaders = customHeaders || [];
|
||||
|
||||
// Add OAuth token if available and no custom headers are set
|
||||
if (finalHeaders.length === 0) {
|
||||
|
|
|
|||
|
|
@ -58,9 +58,7 @@ export const migrateFromLegacyAuth = (
|
|||
bearerToken?: string,
|
||||
headerName?: string,
|
||||
): CustomHeaders => {
|
||||
if (!bearerToken) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [createHeaderFromBearerToken(bearerToken, headerName)];
|
||||
return bearerToken
|
||||
? [createHeaderFromBearerToken(bearerToken, headerName)]
|
||||
: [];
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue