OTP Authentication Flow
Relevant source files
The following files were used as context for generating this wiki page:
The OTP (One-Time Password) Authentication Flow provides a secure, passwordless mechanism for users to access CellarNode dashboards. This system utilizes a two-step verification process: first requesting a code via email, and then verifying that code to receive a JSON Web Token (JWT) for session management.
The flow is integrated across the project through core API abstractions and specialized React UI components. It ensures that users are only granted access if they can provide a valid, time-sensitive code sent to their registered work email address.
Sources: package.json:3-5, src/react/login-form.tsx:181-185
Architectural Overview
The authentication architecture is divided into three primary layers: the UI Layer (React components), the Client/API Layer (request handling), and the Store Layer (token persistence and background refreshing).
Component Interaction
The following diagram illustrates how these layers interact during a standard authentication lifecycle.
The flow begins with an unauthenticated request to trigger the OTP delivery and concludes with a token being stored and managed for future authenticated requests.
Sources: src/auth-api.ts:25-58, src/auth-store.ts:11-21, src/auth-client.ts:33-51
Flow States and Logic
1. Requesting the OTP
The process starts in the LoginForm component where the user enters their email. The system validates the email and calls the requestOtp endpoint. The server returns a response containing timestamps for code expiration and when a resend is permitted.
| Field | Type | Description |
|---|---|---|
expiresAt | string | ISO timestamp when the current OTP will expire. |
resendAvailableAt | string | ISO timestamp when the "Resend" button becomes active. |
Sources: src/types.ts:21-24, src/react/login-form.tsx:138-145
2. Verifying the OTP
Upon receiving the code, the user enters it into the InputOTP component. The verifyOtp function sends the email and code to the backend. If successful, the system extracts the access token from the response using a robust extraction utility that supports various payload structures (e.g., nested data or session objects).
Token Management and Refreshing
Once a token is acquired, the AuthStore manages its lifecycle. To prevent session interruption, the store automatically schedules a background refresh before the token expires.
Refresh Logic
- Buffer: A
refreshBuffer(defaulting to 60 seconds) determines how much earlier the refresh should occur relative to theexpiresInvalue. - Deduplication: The store deduplicates concurrent refresh requests to ensure only one network call is made even if multiple components trigger a refresh simultaneously.
- Retry Mechanism: The
AuthClientincludes a 401-interceptor. If a request fails with an unauthorized status, it attempts exactly one token refresh and retries the original request.
Sources: src/auth-store.ts:11-20, 68-73, src/auth-client.ts:55-68
Error Handling and UI Feedback
The flow implements specific error codes to provide granular feedback to the user.
| Error Code | UI Behavior | Source |
|---|---|---|
USER_NOT_FOUND | Displays "No account found" and optional notFoundContent. | login-form.tsx:64 |
OTP_INVALID | Shows remaining attempts and triggers a "shake" animation on the input. | login-form.tsx:103 |
OTP_MAX_ATTEMPTS | Resets the countdown timers and requires a new code request. | login-form.tsx:111 |
OTP_RATE_LIMIT | Instructs the user to wait before requesting another code. | login-form.tsx:65 |
Sources: src/react/login-form.tsx:63-69, 101-115, src/react/input-otp-slots.tsx:37-43
Summary
The OTP Authentication Flow is a resilient system designed for the CellarNode ecosystem. By combining a two-step React-based interface with an automated background token refresh strategy in the AuthStore, the module provides a seamless and secure user experience. It handles complex edge cases such as token extraction from varied API responses, user type validation during login, and automatic session recovery on 401 errors.
Sources: src/index.ts:1-5, src/auth-client.ts:53-73