Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThe changes implement automatic token refresh on 401 responses in the API client and establish a re-authentication workflow in the Core provider. When a token expires, failed requests are queued, an unauthorized handler obtains a new token, and queued requests are retried with the refreshed credentials. Changes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/api/client.ts (2)
47-73: Potential infinite retry loop if the refreshed token is immediately invalid.When the retried request at line 71 receives another 401, the handler will be invoked again since
_skipUnauthorizedHandleris not set on the retry. This could cause repeated re-auth attempts if the server keeps rejecting the new token.Consider marking the retried request to skip the handler on subsequent failures:
🛡️ Proposed fix to prevent infinite retry
}).then((token) => { error.config.headers["Authorization"] = `Bearer ${token}`; + error.config._skipUnauthorizedHandler = true; return apiClient(error.config); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/client.ts` around lines 47 - 73, The retry logic can cause an infinite loop because the retried request sent by apiClient(error.config) doesn't set _skipUnauthorizedHandler, so another 401 will re-enter the same flow; to fix, when resolving and retrying the queued requests set a flag on the request config (e.g., error.config._skipUnauthorizedHandler = true) before calling apiClient, so references to isRefreshing, unauthorizedHandler, failedRequestsQueue and apiClient remain and you only mark the retried request(s) to skip the handler to prevent repeated refresh attempts.
104-108: Consider skipping the unauthorized handler for theauthenticatecall.The
authenticatefunction is used during the re-authentication flow in the unauthorized handler. If the/authendpoint ever returns a 401 (e.g., due to server misconfiguration), it would trigger recursive handler invocation.🛡️ Proposed fix to prevent recursive refresh
export const authenticate = async ( data: AuthRequest, ): Promise<AuthResponse> => { - const response = await apiClient.post<AuthResponse>("/auth", data); + const response = await apiClient.post<AuthResponse>("/auth", data, { + _skipUnauthorizedHandler: true, + } as any); return response.data; };Alternatively, declare the custom config property via module augmentation to avoid
as any:declare module 'axios' { interface InternalAxiosRequestConfig { _skipUnauthorizedHandler?: boolean; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/client.ts` around lines 104 - 108, The authenticate function can trigger the unauthorized handler recursively if the /auth call returns 401; update authenticate to call apiClient.post with a request config that marks the request to skip the unauthorized handler (e.g., set a custom flag like _skipUnauthorizedHandler) so the global handler ignores this refresh attempt, and optionally add the module augmentation for axios InternalAxiosRequestConfig to declare _skipUnauthorizedHandler?: boolean to avoid using any casts; reference authenticate and apiClient.post to implement this change.src/providers/Core.tsx (1)
49-85: Consider extracting the duplicate message creation logic.The nonce/expiry/message construction (lines 61-68) duplicates the logic in
connect()(lines 119-129). Extracting this into a shared helper would reduce duplication and ensure consistency.♻️ Example helper extraction
const createAuthMessage = (address: string) => { const nonce = hexlify(randomBytes(16)); const expiryTime = new Date(Date.now() + 15 * 60 * 1000).toISOString(); return JSON.stringify({ message: "Sign into Vultisig Developer Portal", nonce, expiresAt: expiryTime, address, }); };Then use
createAuthMessage(address)in both the unauthorized handler andconnect().🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/providers/Core.tsx` around lines 49 - 85, Extract the duplicated nonce/expiry/message construction into a shared helper (e.g., createAuthMessage) and replace the inline logic in both the setUnauthorizedHandler callback and the connect() function with a call to that helper; ensure the helper returns the exact JSON string used for signing so calls in setUnauthorizedHandler and connect continue to pass the returned value into personalSign and authenticate unchanged, and update any references to use the new helper name (createAuthMessage) to keep nonce and expiresAt generation consistent across setUnauthorizedHandler and connect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/api/client.ts`:
- Around line 47-73: The retry logic can cause an infinite loop because the
retried request sent by apiClient(error.config) doesn't set
_skipUnauthorizedHandler, so another 401 will re-enter the same flow; to fix,
when resolving and retrying the queued requests set a flag on the request config
(e.g., error.config._skipUnauthorizedHandler = true) before calling apiClient,
so references to isRefreshing, unauthorizedHandler, failedRequestsQueue and
apiClient remain and you only mark the retried request(s) to skip the handler to
prevent repeated refresh attempts.
- Around line 104-108: The authenticate function can trigger the unauthorized
handler recursively if the /auth call returns 401; update authenticate to call
apiClient.post with a request config that marks the request to skip the
unauthorized handler (e.g., set a custom flag like _skipUnauthorizedHandler) so
the global handler ignores this refresh attempt, and optionally add the module
augmentation for axios InternalAxiosRequestConfig to declare
_skipUnauthorizedHandler?: boolean to avoid using any casts; reference
authenticate and apiClient.post to implement this change.
In `@src/providers/Core.tsx`:
- Around line 49-85: Extract the duplicated nonce/expiry/message construction
into a shared helper (e.g., createAuthMessage) and replace the inline logic in
both the setUnauthorizedHandler callback and the connect() function with a call
to that helper; ensure the helper returns the exact JSON string used for signing
so calls in setUnauthorizedHandler and connect continue to pass the returned
value into personalSign and authenticate unchanged, and update any references to
use the new helper name (createAuthMessage) to keep nonce and expiresAt
generation consistent across setUnauthorizedHandler and connect.
Fix #5
Summary by CodeRabbit
New Features
Bug Fixes