Skip to main content
Glama
EnterpriseAuthCheck.tsx5.76 kB
import { useEffect, useState } from "react"; import { getRuntimeConfigSync } from "@/config/runtime-config"; import { getMcpxServerURL } from "@/config/api-config"; import { useRef } from "react"; export type EnterpriseAuthState = { isLoading: boolean; isAuthenticated: boolean; error: string | null; isPendingAllocation: boolean; }; type UseEnterpriseAuthOptions = { enabled?: boolean; }; // Hook version so routers or views can decide what to render export function useEnterpriseAuth( options: UseEnterpriseAuthOptions = {}, ): EnterpriseAuthState { const { enabled = true } = options; const [state, setState] = useState<EnterpriseAuthState>({ isLoading: true, isAuthenticated: false, error: null, isPendingAllocation: false, }); const wasPendingRef = useRef(false); useEffect(() => { wasPendingRef.current = state.isPendingAllocation; }, [state.isPendingAllocation]); useEffect(() => { let isMounted = true; let retryTimeout: ReturnType<typeof setTimeout> | null = null; const checkAuth = async () => { if (!isMounted) return; if (retryTimeout) { clearTimeout(retryTimeout); retryTimeout = null; } const wasPending = wasPendingRef.current; try { const runtimeConfig = getRuntimeConfigSync(); const isEnterpriseEnabled = runtimeConfig.VITE_ENABLE_ENTERPRISE === "true" || import.meta.env.VITE_ENABLE_ENTERPRISE === "true"; if (!isEnterpriseEnabled) { if (!isMounted) return; setState({ isLoading: false, isAuthenticated: true, error: null, isPendingAllocation: false, }); return; } if (!enabled) { if (!isMounted) return; setState({ isLoading: false, isAuthenticated: false, error: null, isPendingAllocation: false, }); return; } if (!isMounted) return; setState((prev) => ({ ...prev, isLoading: prev.isPendingAllocation ? false : true, isAuthenticated: false, error: null, })); const response = await fetch(`${getMcpxServerURL("http")}/auth/mcpx`, { method: "GET", headers: { "Content-Type": "application/json", }, credentials: "include", }); if (response.status === 503) { const message = (await safeReadError(response)) || "Your MCPX workspace is being provisioned. We'll connect automatically when it's ready."; if (!isMounted) return; setState({ isLoading: false, isAuthenticated: false, error: message, isPendingAllocation: true, }); retryTimeout = setTimeout(checkAuth, 1000); return; } const payload = (await safeReadJson(response)) as { status?: string; error?: string; } | null; if (!isMounted) return; if (response.ok && payload && payload.status === "authenticated") { setState({ isLoading: false, isAuthenticated: true, error: null, isPendingAllocation: false, }); } else { // In enterprise mode, if we get non-auth errors (like 500s, 502s, 504s), // we should keep retrying as the server might be starting up. // Only 401/403 should trigger immediate failure. const isAuthError = response.status === 401 || response.status === 403; if (!isAuthError) { setState({ isLoading: false, isAuthenticated: false, error: "Connecting to MCPX server...", isPendingAllocation: true, }); retryTimeout = setTimeout(checkAuth, 1000); return; } setState({ isLoading: false, isAuthenticated: false, error: payload?.error || (!response.ok ? `Authentication check failed (${response.status})` : "You are not authenticated to the MCPX."), isPendingAllocation: false, }); return; } setState({ isLoading: false, isAuthenticated: true, error: null, isPendingAllocation: false, }); if (wasPending && typeof window !== "undefined") { window.location.reload(); } } catch (err) { console.error("Auth check failed:", err); if (!isMounted) return; // Retry on network errors in enterprise mode setState({ isLoading: false, isAuthenticated: false, error: "Unable to connect to MCPX server. Retrying...", isPendingAllocation: true, }); retryTimeout = setTimeout(checkAuth, 1000); } }; checkAuth(); return () => { isMounted = false; if (retryTimeout) { clearTimeout(retryTimeout); } }; }, [enabled]); return state; } async function safeReadJson(response: Response): Promise<unknown> { try { return await response.json(); } catch { return null; } } async function safeReadError(response: Response): Promise<string | null> { try { const data = await response.json(); if (typeof data?.error === "string") return data.error; if (typeof data?.message === "string") return data.message; } catch { /* ignore */ } try { const text = await response.text(); return text || null; } catch { return null; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheLunarCompany/lunar'

If you have feedback or need assistance with the MCP directory API, please join our Discord server