Skip to content

feat(api-client): extend OAuthProvider with automatic token lifecycle, JWT exp decoding, and rotation #56

Description

@crapougnax

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions