Skip to content

Refresh, CSRF, and Sensitive Guards

These options change behavior around 401, 419, 429, and mutations. They must be documented in the consuming application.

Bearer Refresh Single-Flight

import { bearerAuth, bearerRefreshGuard, createHttpClient } from "@cedvict/http-guardian";

const api = createHttpClient({
  baseUrl: "https://api.example.com",
  auth: bearerAuth(() => tokenStore.access()),
  parser,
  guards: [
    bearerRefreshGuard({
      refreshFn: () => tokenStore.refresh(),
      onTokenRefreshed: ({ accessToken }) => tokenStore.setAccess(accessToken),
      skipRefreshFor: (ctx) => ctx.url.includes("/auth/")
    })
  ]
});
Option Default Explanation
refreshFn None Function called only once for a wave of concurrent 401 responses.
onTokenRefreshed No hook Persists the new token before replaying queued requests.
skipRefreshFor No application skip Excludes login, refresh, logout, health, or public endpoints.
triggerStatuses [401] Statuses that trigger Bearer refresh.
queueTimeoutMs 30000 Maximum wait time during single-flight refresh.

Refresh loop

refreshFn must not call the same protected client without noAuth, otherwise refresh can trigger refresh again.

cookieSafeRefreshGuard({
  refreshPath: "/auth/refresh",
  excludePaths: ["/auth/login", "/auth/refresh", "/health"]
})
Option Default Explanation
refreshPath None Dedicated endpoint for cookie refresh.
triggerStatuses [401, 419] 419 often covers expired session or invalid CSRF.
maxRetry 1 Number of replays of the original request after refresh.
excludePaths [] Pathnames ignored by refresh logic.
honorRetryAfter true Honors Retry-After or applies cooldown on 429.

CSRF

csrfGuard({
  tokenFromCookie: "csrf_token",
  tokenFromHeader: "X-CSRF-Token",
  headerName: "X-CSRF-Token"
})
Option Default Explanation
tokenFromCookie Disabled Reads a non-HttpOnly browser cookie.
tokenFromHeader Disabled Remembers the last non-empty response header value.
headerName X-CSRF-Token Header injected on mutations.
applyTo POST, PUT, PATCH, DELETE Affected methods.

The backend must expose the CSRF header through CORS if the browser needs to read it.