@mrzr/api-client

Authentication

Log users in with bearer tokens or httpOnly cookies. Choose where tokens are stored, restore a cookie session on page load and enable CSRF protection.

The client owns the tokens. You never set an Authorization header or read storage yourself.

Two modes

authMode: "header" (default)authMode: "cookie"
How the credential travelsAuthorization: Bearer <token>httpOnly cookie set by your server
Can page JavaScript read it?No, in worker modeNo
Needs CSRF protection?NoYes
Good forSPAs and APIs on another domainApps where you control the backend

Header mode

const api = createClient({ baseUrl: "https://api.example.com" });

await api.login({ email, password });   // tokens captured from the response
await api.get("/me");                   // Authorization: Bearer … attached
await api.logout();

The token is only ever sent to the baseUrl origin and the page's own origin. To send it to another API of yours, list that origin:

createClient({ baseUrl, authOrigins: ["https://files.example.com"] });

Already have tokens, for example from an OAuth callback or SSR? Seed them with api.setTokens({ accessToken, refreshToken }).

Where tokens are stored

storageSurvives reloadReadable by page JS
"memory" (default)NoNo: the token never leaves the worker
"session"Same tab onlyYes
"local"YesYes
"cookie"Yes (readable cookie, not httpOnly)Yes

"memory" is the safest option. The user logs in again after a reload, unless the refresh token survives in an httpOnly cookie on your server. You can also pass your own adapter: any object with get, set and clear.

Your server sets HttpOnly; Secure cookies at login. The client never sees a token. It just sends requests with credentials: "include".

const api = createClient({
  baseUrl: "https://api.example.com",
  authMode: "cookie",
  xsrfCookieName: "csrftoken",   // see CSRF below
});

JavaScript can't see httpOnly cookies, so after a page reload the client doesn't know whether a session exists. Ask the server once on startup:

const { isAuthenticated, user } = await api.restoreSession("/auth/me");

Without a URL, restoreSession() tries the refresh endpoint instead.

CSRF

With cookies, a malicious site can make the browser send your cookie along with a forged request. The standard defence is the double-submit pattern: the server sets a readable CSRF cookie, and the client copies its value into a header.

createClient({ authMode: "cookie", xsrfCookieName: "csrftoken" });
// POST/PUT/PATCH/DELETE and refresh → X-CSRF-Token: <cookie value>

If the token isn't in a cookie (for example it's in a <meta> tag), use getCsrfToken: () => … instead. Your server must still compare the header with the cookie and reject mismatches.

Auth state

const state = await api.getAuthState();   // { isAuthenticated, expiresAt, user }
const off = api.onAuthStateChange((state) => { /* … */ });

The state never contains tokens. onAuthFailure in the client options fires when the session is gone for good: the refresh endpoint rejected it (401/403), or the user logged out in any tab.

On this page