Shared `fetch` wrapper for embedded surfaces (chat, ticket center, widgets) that attaches bearer-act-as identity headers (`Authorization` + `X-Chat-Act-As`) from proxy auth storage, with support for host-supplied auth adapters, cross-origin defense, and 401 self-healing. ## Key Components ### Interfaces - **`EmbedAuthAdapter`** — Interface for host-supplied auth overrides. Supports `getHeaders()`, `credentials`, `refresh` (401 self-heal), and `allowedOrigins` (native-shell hatch for cross-origin allowlisting). ### Functions | Function | Description | |---|---| | `setEmbedAuthAdapter(adapter)` | Registers (or clears) a host-owned auth adapter at the `globalThis` slot `__embedAuthedFetchAdapter__`. Warns on overwrite in non-production. | | `hasEmbedAuthAdapter()` | Returns `true` when an adapter is currently registered; used by sibling helpers to route through `embedAuthedFetch` only when embedded auth is active. | | `needsBearerAssetFetch(url)` | Returns `true` when the URL's origin is in the adapter's `allowedOrigins` AND the adapter is supplying an `Authorization` header — signals that native asset loads (``) must use fetch + blob object-URL instead. | | `embedAuthedFetch(url, init?)` | Drop-in `fetch` replacement. Merges proxy auth headers, enforces same-origin (or `allowedOrigins`) guard synchronously, and performs a single 401 refresh + retry when `adapter.refresh` is registered. | ## Usage Example ```typescript import { setEmbedAuthAdapter, embedAuthedFetch, needsBearerAssetFetch, } from './embed-authed-fetch' // Register a host adapter on provider mount setEmbedAuthAdapter({ getHeaders: () => ({ Authorization: token ? `Bearer ${token}` : undefined, }), credentials: 'include', refresh: async () => { const refreshed = await refreshAccessToken() return refreshed }, allowedOrigins: ['https://gateway.example.com'], }) // Use as a drop-in fetch replacement for /api/chat/* routes const response = await embedAuthedFetch('/api/chat/messages', { method: 'POST', body: JSON.stringify({ message: 'Hello' }), }) // Route asset loads through fetch when bearer is required if (needsBearerAssetFetch(imageUrl)) { const res = await embedAuthedFetch(imageUrl) const blob = await res.blob() imgElement.src = URL.createObjectURL(blob) } // Clear adapter on provider unmount setEmbedAuthAdapter(null) ``` > **Note:** The adapter is stored on `globalThis` (key `__embedAuthedFetchAdapter__`) rather than module scope to survive bundler code-splitting across multiple entry points. Routes that do not need bearer-act-as (e.g. `/api/profile/me`) should continue using vanilla `fetch`. ## Source [`embed-authed-fetch.ts`](https://github.com/flamingo-stack/openframe-oss-lib/blob/main/embed-authed-fetch.ts)