Documentation

Authentication

Read tokens, refresh expired sessions, attach auth headers, and choose auth behavior per endpoint.

Authentication overview

Authentication is optional.

If your API needs auth, create a token provider and pass it to createMicroApi.

The token provider is the small object that knows where your tokens live and how to refresh them.

Create a token provider

createTokenProvider keeps auth logic in one place.

It reads the current access token, can call your refresh endpoint, and lets you save or clear tokens after refresh.

When several requests receive 401 at the same time, they share one refresh call instead of starting many refresh requests.

Key points

  • getAccessToken returns the current access token or null.
  • getRefreshToken returns the refresh token when your refresh flow needs one.
  • refresh.fn calls your refresh endpoint.
  • refresh.selectAccessToken picks the new access token from the refresh response.
  • refresh.onSuccess is where you save returned tokens.
  • refresh.onError is where you clear auth state or notify the app.
TypeScript
1import { createTokenProvider } from "micro-rq";2 3export const tokenProvider = createTokenProvider({4  getAccessToken: () => localStorage.getItem("accessToken"),5  getRefreshToken: () => localStorage.getItem("refreshToken"),6  refresh: {7    fn: async ({ refreshToken }) => {8      const { auth } = await import("./auth");9 10      return auth.refresh.fn({ refreshToken });11    },12    selectAccessToken: (tokens) => tokens.accessToken,13    onSuccess: (tokens) => {14      localStorage.setItem("accessToken", tokens.accessToken);15      localStorage.setItem("refreshToken", tokens.refreshToken);16    },17    onError: () => {18      localStorage.removeItem("accessToken");19      localStorage.removeItem("refreshToken");20    },21  },22});
TypeScript
1import { createMicroApi } from "micro-rq";2import { tokenProvider } from "./token-provider";3 4export const api = createMicroApi({5  name: "main",6  baseUrl: "/api",7  tokenProvider,8  authHeader: (token) => ({9    Authorization: `Bearer ${token}`,10  }),11});
TypeScript
1import { api } from "./api";2 3type AuthTokens = {4  accessToken: string;5  refreshToken: string;6};7 8export const auth = api.resource("auth", {9  refresh: api.post<AuthTokens, { refreshToken?: string | null }>("/auth/refresh", {10    authMode: "none",11  }),12});

Warning

Refresh endpoint warning

A refresh request should not trigger the same refresh flow again.

If your refresh endpoint uses the same authenticated api, set that endpoint to authMode: "none".

Without that, a failed refresh request can try to refresh itself and create a loop.

If the refresh endpoint needs its own auth behavior, put it on a separate API client.

TypeScript
1export const publicApi = createMicroApi({2  name: "public",3  baseUrl: "/api",4});5 6export const auth = publicApi.resource("auth", {7  refresh: publicApi.post<AuthTokens, { refreshToken?: string | null }>(8    "/auth/refresh",9    {10      // Use "optional" or "required" when this refresh endpoint11      // has its own auth behavior and cannot be authMode: "none".12      authMode: "optional",13    },14  ),15});

Attach auth to the API client

After creating the token provider, attach it to your API client.

Use authHeader to turn the access token into request headers.

Most APIs use a Bearer token, but you can return any header shape your backend expects.

TypeScript
1export const api = createMicroApi({2  name: "main",3  baseUrl: "/api",4  tokenProvider,5  authHeader: (token) => ({6    Authorization: `Bearer ${token}`,7  }),8});

Endpoint auth modes

Each endpoint can choose how it uses auth.

optional is the default. It uses a token when one exists, but still allows the request without one.

Use none for endpoints like login and refresh.

Use required when the request must have a token before fetch runs.

Key points

  • optional uses a token when one exists.
  • required throws MicroAuthRequiredError before fetch when no token exists.
  • none skips token lookup, auth headers, and refresh-on-401.
TypeScript
1export const auth = api.resource("auth", {2  login: api.post<LoginResponse, LoginDto>("/auth/login", {3    authMode: "none",4  }),5  profile: api.get<AuthUser>("/auth/profile", {6    // Optional is the default value; this line can be omitted.7    authMode: "optional",8  }),9  me: api.get<AuthUser>("/auth/me", {10    authMode: "required",11  }),12});