Documentation

HttpOnly Cookies

Use same-origin or cross-origin cookie sessions with optional automatic refresh after 401.

HttpOnly cookie sessions

With an HttpOnly session, the backend creates or removes the cookie through Set-Cookie, and the browser sends it with later requests.

JavaScript and micro-rq do not read the cookie value. For ordinary cookie authentication, no tokenProvider or authHeader is needed.

Use API-level refresh only when a 401 should call a refresh endpoint and retry the original request.

Browser
stores and sends the HttpOnly cookie.
Backend
creates, rotates, expires, and validates the session.
micro-rq
performs requests and optionally coordinates refresh after 401.
TanStack Query
controls query caching, retries, invalidation, and refetching.

Same-origin setup

When the frontend and API share an origin, the default fetch credentials mode sends same-origin cookies and accepts Set-Cookie responses.

Login and logout remain normal mutation endpoints. The backend sets or expires the cookie in its response.

TypeScript
1export const api = createMicroApi({2  name: "main",3  baseUrl: "/api",4});5 6export const auth = api.resource("auth", {7  login: api.post<User, LoginDto>("/auth/login", {8    authMode: "none",9  }),10  logout: api.post<void>("/auth/logout"),11});
TypeScript
1Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/

Cross-origin setup

When the API has another origin, wrap fetch with credentials: "include" and use that fetcher for login, refresh, logout, and protected requests.

The backend must allow credentialed CORS requests from the exact frontend origin. A wildcard Access-Control-Allow-Origin cannot be used with credentials.

Cross-site cookies normally require SameSite=None; Secure. Browser privacy rules may still restrict third-party cookies, so same-site deployment or an application proxy is often simpler.

TypeScript
1const cookieFetcher: typeof fetch = (input, init) =>2  fetch(input, {3    ...init,4    credentials: "include",5  });6 7export const api = createMicroApi({8  name: "main",9  baseUrl: "https://api.example.com",10  fetcher: cookieFetcher,11});
TypeScript
1Access-Control-Allow-Origin: https://app.example.com2Access-Control-Allow-Credentials: true3Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=None; Path=/

Automatic refresh after 401

Configure API-level refresh when the backend uses a refresh cookie or session endpoint to replace the HttpOnly access cookie.

The refresh endpoint may return 204 No Content; micro-rq does not require response data.

Parallel 401 responses share one refresh operation. After it succeeds, every original request retries once.

Configure refresh either at the API level for cookie sessions or inside tokenProvider for readable tokens, not both.

TypeScript
1const authApi = createMicroApi({2  name: "auth",3  baseUrl: "/api",4});5 6const auth = authApi.resource("auth", {7  refresh: authApi.post<void>("/auth/refresh", {8    authMode: "none",9  }),10});11 12export const api = createMicroApi({13  name: "main",14  baseUrl: "/api",15  refresh: {16    fn: () => auth.refresh.fn(),17  },18});

Auth modes and refresh loops

Use the default authMode: "optional" for protected cookie endpoints. The cookie is intentionally unreadable, so micro-rq cannot check whether it exists before fetch.

Do not use authMode: "required" for HttpOnly sessions. That mode requires a readable access token from tokenProvider and throws before fetch when it is missing.

Use authMode: "none" for login and refresh endpoints so their own 401 responses do not start the refresh flow.

CSRF and server rendering

Cookie-authenticated write requests need suitable CSRF protection. Choose SameSite carefully and send a CSRF token/header when your backend requires one.

In the browser, cookies are handled automatically. During SSR, server-side fetch does not automatically use the browser's cookie jar.

For SSR session requests, forward the incoming Cookie header. If an SSR response refreshes the session, also propagate its Set-Cookie header through your framework's outgoing response.