fix(auth): await OAuth storage load() to fix remote OAuth races
This commit is contained in:
parent
7bd26c938e
commit
a24091484c
2 changed files with 245 additions and 133 deletions
|
|
@ -1,13 +1,14 @@
|
|||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import { BrowserOAuthStorage } from "@inspector/core/auth/browser/storage.js";
|
||||
import type { InspectorClient } from "@inspector/core/mcp/inspectorClient.js";
|
||||
import { clearServerOAuthState } from "./clearServerOAuthState";
|
||||
|
||||
describe("clearServerOAuthState", () => {
|
||||
let storage: BrowserOAuthStorage;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
storage = new BrowserOAuthStorage();
|
||||
storage.clear("https://mcp.example.com/mcp");
|
||||
await storage.clear("https://mcp.example.com/mcp");
|
||||
});
|
||||
|
||||
it("clears storage by server URL when not the active connection", async () => {
|
||||
|
|
@ -16,7 +17,7 @@ describe("clearServerOAuthState", () => {
|
|||
token_type: "Bearer",
|
||||
});
|
||||
|
||||
const cleared = clearServerOAuthState({
|
||||
const cleared = await clearServerOAuthState({
|
||||
config: { type: "streamable-http", url: "https://mcp.example.com/mcp" },
|
||||
isActiveConnection: false,
|
||||
oauthStorage: storage,
|
||||
|
|
@ -28,11 +29,11 @@ describe("clearServerOAuthState", () => {
|
|||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("uses the live client when clearing the active connection", () => {
|
||||
const clearOAuthTokens = vi.fn<() => void>();
|
||||
it("uses the live client when clearing the active connection", async () => {
|
||||
const clearOAuthTokens = vi.fn<InspectorClient["clearOAuthTokens"]>();
|
||||
const inspectorClient = { clearOAuthTokens };
|
||||
|
||||
const cleared = clearServerOAuthState({
|
||||
const cleared = await clearServerOAuthState({
|
||||
config: { type: "streamable-http", url: "https://mcp.example.com/mcp" },
|
||||
inspectorClient,
|
||||
isActiveConnection: true,
|
||||
|
|
@ -43,13 +44,13 @@ describe("clearServerOAuthState", () => {
|
|||
expect(clearOAuthTokens).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("returns false for stdio servers", () => {
|
||||
expect(
|
||||
it("returns false for stdio servers", async () => {
|
||||
await expect(
|
||||
clearServerOAuthState({
|
||||
config: { type: "stdio", command: "node", args: [] },
|
||||
isActiveConnection: false,
|
||||
oauthStorage: storage,
|
||||
}),
|
||||
).toBe(false);
|
||||
).resolves.toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,18 +17,18 @@ export interface ClearServerOAuthStateParams {
|
|||
* HTTP MCP server. When clearing the active connection, uses the live client so
|
||||
* in-memory flow state is reset too.
|
||||
*/
|
||||
export function clearServerOAuthState(
|
||||
export async function clearServerOAuthState(
|
||||
params: ClearServerOAuthStateParams,
|
||||
): boolean {
|
||||
): Promise<boolean> {
|
||||
const serverUrl = getOAuthServerUrl(params.config);
|
||||
if (!serverUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.isActiveConnection && params.inspectorClient) {
|
||||
params.inspectorClient.clearOAuthTokens();
|
||||
await params.inspectorClient.clearOAuthTokens();
|
||||
} else {
|
||||
params.oauthStorage.clear(serverUrl);
|
||||
await params.oauthStorage.clear(serverUrl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue