Auth State Synchronization
Relevant source files
The following files were used as context for generating this wiki page:
The Auth State Synchronization system in CellarNode manages the lifecycle of authentication tokens, ensuring that the client application maintains a valid session without manual user intervention. It coordinates token storage, automatic background refreshing, and proactive re-authentication when tokens expire or requests fail.
The system is built around a centralized AuthStore that maintains the current access token and manages a background refresh timer. This store works in tandem with the AuthClient, which intercepts network requests to inject credentials and handles 401 Unauthorized responses by attempting a synchronized token refresh.
Core Architecture and Components
The synchronization logic is distributed across three primary modules that interact to maintain a consistent authentication state.
| Component | Responsibility |
|---|---|
AuthStore | Holds the in-memory token, manages the refresh timer, and provides methods to ensure a valid token exists. |
AuthClient | A wrapper around the fetch API that automatically adds Authorization headers and handles retries. |
AuthApi | Provides high-level methods for authentication actions (login, logout, register) that update the store. |
Sources: src/types.ts:47-81, src/auth-store.ts:4-66
Component Interaction Diagram
The following diagram illustrates how the components interact to provide a seamless authentication experience.
The AuthClient relies on the AuthStore for tokens, while the AuthStore communicates with the backend to refresh them. The AuthApi acts as the primary entry point for initial token acquisition.
Sources: src/auth-client.ts:25-60, src/auth-store.ts:16-36
Token Management Lifecycle
The lifecycle of an authentication state begins with token acquisition via AuthApi.verifyOtp and is maintained through the AuthStore's internal mechanisms.
Token Acquisition and Extraction
When a user verifies their OTP, the AuthApi receives a response containing an access token and an expiration time. The system uses a flexible extraction utility to locate the token within various possible response structures (e.g., flat, nested in data, or nested in session).
Sources: src/auth-api.ts:33-53, src/extract-token.ts:1-22
Background Refresh Logic
Once a token is set in the store using setAccessToken(token, expiresIn), a background timer is scheduled. The refresh occurs at a configurable interval before the actual expiry (the refreshBuffer), defaulting to 60 seconds before the token becomes invalid.
The store uses setTimeout to trigger the performRefresh function, which makes a credentialed POST request to the server's refresh endpoint.
Sources: src/auth-store.ts:10-36, tests/auth-store.test.ts:39-58
Concurrency and Synchronization
To prevent redundant network traffic and potential race conditions, the system implements deduplication for concurrent refresh requests.
Deduping Refresh Requests
If multiple parts of the application call ensureAccessToken(true) simultaneously—or if a background refresh is triggered while a manual one is in progress—the AuthStore captures the ongoing refresh in a refreshPromise. Subsequent calls return the same promise instead of initiating new HTTP requests.
Sources: src/auth-store.ts:60-65, tests/auth-store.test.ts:68-84
Request Interception and Retry
The AuthClient implements a proactive synchronization strategy when dealing with expired sessions. If a request returns a 401 status:
- The client intercepts the failure.
- It requests a "forced refresh" from the
AuthStoreviaensureAccessToken(true). - If successful, it updates the headers and retries the original request exactly once.
- If the refresh fails, it clears the store and triggers an
onAuthFailurecallback (e.g., redirecting to login).
Sources: src/auth-client.ts:51-70, tests/auth-client.test.ts:80-101
Configuration Options
The behavior of the synchronization logic can be tuned via the AuthStoreConfig.
| Option | Type | Default | Description |
|---|---|---|---|
baseUrl | string | (Required) | The base URL for the authentication server. |
refreshPath | string | "/auth/refresh" | The endpoint used for token refreshing. |
refreshBuffer | number | 60 | Seconds before expiry to trigger the background refresh. |
Sources: src/types.ts:41-45, src/auth-store.ts:5-6
Summary of Auth State Synchronization
The system ensures auth state consistency by centralizing token logic in an in-memory AuthStore that manages time-based background refreshes and promise-based request deduplication. By integrating this store with a specialized AuthClient, the application can transparently handle token rotation and session expiration, providing a robust and seamless experience for users across different dashboards.
Sources: src/index.ts:1-26, README.md:1-28