// @vitest-environment jsdom import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { AUTH_INVALID_EVENT, createLlmProviderProfile, listDevices, login, registerPlugin, } from "./api"; function response(payload: unknown, status = 200): Response { return new Response(JSON.stringify(payload), { status, headers: { "Content-Type": "application/json" }, }); } describe("Cloud Console API authentication", () => { beforeEach(() => { document.cookie = "amcp_csrf=; Max-Age=0; path=/"; vi.stubGlobal("fetch", vi.fn()); }); afterEach(() => { vi.unstubAllGlobals(); }); it("uses credentialed account login without a bearer header", async () => { vi.mocked(fetch).mockResolvedValueOnce( response({ id: "user-a", username: "admin", display_name: "Administrator", role: "admin", enabled: true, must_change_password: false, scopes: ["*"], created_at: "2026-01-01T00:00:00+00:00", updated_at: "2026-01-01T00:00:00+00:00", last_login_at: null, }), ); await login("admin", "correct-horse-battery-staple"); expect(fetch).toHaveBeenCalledWith( expect.stringMatching(/\/v1\/auth\/login$/), expect.objectContaining({ credentials: "include", headers: expect.not.objectContaining({ Authorization: expect.any(String) }), }), ); }); it("uses CSRF proof for session-authenticated writes", async () => { document.cookie = "amcp_csrf=csrf-value; path=/"; vi.mocked(fetch).mockResolvedValueOnce( response({ name: "demo", version: "1", entry_point_kind: "tool", target: "m:t", wired: false }), ); await registerPlugin({ name: "demo", version: "1", entry_point_kind: "tool", target: "m:t", }); expect(fetch).toHaveBeenCalledWith( expect.stringMatching(/\/v1\/plugins$/), expect.objectContaining({ credentials: "include", headers: expect.objectContaining({ "X-CSRF-Token": "csrf-value" }), }), ); }); it("sends a Provider profile write through the CSRF-protected management API", async () => { document.cookie = "amcp_csrf=csrf-value; path=/"; vi.mocked(fetch).mockResolvedValueOnce( response({ id: "provider-a", name: "OpenAI compatible", provider_type: "openai-compatible", model: "model-a", base_url: "https://compat.example/v1", timeout_seconds: 30, enabled: true, revision: 1, has_api_key: true, key_last_rotated_at: "2026-01-01T00:00:00+00:00", created_at: "2026-01-01T00:00:00+00:00", updated_at: "2026-01-01T00:00:00+00:00", active: false, }), ); await createLlmProviderProfile({ name: "OpenAI compatible", provider_type: "openai-compatible", model: "model-a", base_url: "https://compat.example/v1", timeout_seconds: 30, api_key: "secret-value", }); expect(fetch).toHaveBeenCalledWith( expect.stringMatching(/\/v1\/planner\/providers$/), expect.objectContaining({ method: "POST", headers: expect.objectContaining({ "X-CSRF-Token": "csrf-value" }), }), ); }); it("invalidates the session only on 401", async () => { const invalidated = vi.fn(); window.addEventListener(AUTH_INVALID_EVENT, invalidated); vi.mocked(fetch).mockResolvedValueOnce(response({ detail: "unauthorized" }, 401)); await expect(listDevices()).rejects.toMatchObject({ status: 401 }); expect(invalidated).toHaveBeenCalledTimes(1); vi.mocked(fetch).mockResolvedValueOnce(response({ detail: "forbidden" }, 403)); await expect(listDevices()).rejects.toMatchObject({ status: 403 }); expect(invalidated).toHaveBeenCalledTimes(1); window.removeEventListener(AUTH_INVALID_EVENT, invalidated); }); });