Context & Motivation
Currently, OAuthProvider in @quatrain/api-client (packages/api-client/src/auth/OAuthProvider.ts) is only a thin wrapper around a callback:
constructor(tokenFetcher: () => Promise<string>)
As a consequence, applications using @quatrain/api-client (such as @totalymage/backoffice-ui) are maintaining ad-hoc local legacy wrappers to handle token storage, expiration checking, single-flight refresh calls, and token rotation.
To enable applications to adopt @quatrain/api-client directly without local wrapper boilerplate, @quatrain/api-client should provide an autonomous, robust OAuth token lifecycle management strategy.
Proposed Features & Requirements
1. Robust JWT Expiration Decoding (getJwtExpiration)
- Extract the standard
exp claim from the access token JWT (RFC 7519) without heavy external dependencies.
- Use the server-issued absolute timestamp (
exp * 1000) as the primary source of truth for token TTL, avoiding reliance on relative JSON payload fields (expiresIn vs expires_in).
2. Autonomous Token Lifecycle Manager in OAuthProvider
Provide a full-featured OAuthProvider (or ManagedOAuthProvider) with:
- Configurable Storage Adapter: Pluggable storage interface (
getItem, setItem, removeItem) with built-in LocalStorageAdapter for browsers and MemoryStorageAdapter for Node/SSR.
- Proactive Expiration Buffer: Configurable buffer (default: 60s) to trigger renewal before the token expires.
- Single-Flight Concurrency Control: Mutex/deduplication promise preventing multiple simultaneous API requests from triggering parallel refresh calls (anti-stampede).
- Refresh Token Rotation (RTR) Support: Automatically update and persist the newly issued
refreshToken on every renewal cycle.
- Session Lifecycle Callbacks: Hooks for
onTokenRotated, onSessionExpired (e.g. to redirect to sign-in on invalid refresh token).
3. ApiClient Core Ergonomics
- Default Headers: Allow defining default headers at the client instance level (e.g.
X-Client-ID: backoffice) that merge automatically into all outbound requests.
- Binary/Blob Helper (
getBlob): Native method to fetch authenticated binary blobs (Response.blob()) for media/image rendering and downloads.
4. Quality & Compliance Standards
- Strict TypeScript: 100% typed interfaces, strictly no
as any, @ts-ignore, or @ts-nocheck.
- Comprehensive unit tests in
packages/api-client/src/auth/OAuthProvider.test.ts and ApiClient.test.ts validating concurrent refresh, expiration calculations, and error handling.
Context & Motivation
Currently,
OAuthProviderin@quatrain/api-client(packages/api-client/src/auth/OAuthProvider.ts) is only a thin wrapper around a callback:As a consequence, applications using
@quatrain/api-client(such as@totalymage/backoffice-ui) are maintaining ad-hoc local legacy wrappers to handle token storage, expiration checking, single-flight refresh calls, and token rotation.To enable applications to adopt
@quatrain/api-clientdirectly without local wrapper boilerplate,@quatrain/api-clientshould provide an autonomous, robust OAuth token lifecycle management strategy.Proposed Features & Requirements
1. Robust JWT Expiration Decoding (
getJwtExpiration)expclaim from the access token JWT (RFC 7519) without heavy external dependencies.exp * 1000) as the primary source of truth for token TTL, avoiding reliance on relative JSON payload fields (expiresInvsexpires_in).2. Autonomous Token Lifecycle Manager in
OAuthProviderProvide a full-featured
OAuthProvider(orManagedOAuthProvider) with:getItem,setItem,removeItem) with built-inLocalStorageAdapterfor browsers andMemoryStorageAdapterfor Node/SSR.refreshTokenon every renewal cycle.onTokenRotated,onSessionExpired(e.g. to redirect to sign-in on invalid refresh token).3.
ApiClientCore ErgonomicsX-Client-ID: backoffice) that merge automatically into all outbound requests.getBlob): Native method to fetch authenticated binary blobs (Response.blob()) for media/image rendering and downloads.4. Quality & Compliance Standards
as any,@ts-ignore, or@ts-nocheck.packages/api-client/src/auth/OAuthProvider.test.tsandApiClient.test.tsvalidating concurrent refresh, expiration calculations, and error handling.