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
getAccessTokenreturns the current access token ornull.getRefreshTokenreturns the refresh token when your refresh flow needs one.refresh.fncalls your refresh endpoint.refresh.selectAccessTokenpicks the new access token from the refresh response.refresh.onSuccessis where you save returned tokens.refresh.onErroris where you clear auth state or notify the app.
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});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});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.
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.
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
optionaluses a token when one exists.requiredthrowsMicroAuthRequiredErrorbefore fetch when no token exists.noneskips token lookup, auth headers, and refresh-on-401.
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});