Skip to content

fix: tokens#113

Draft
kah-seng wants to merge 1 commit intomainfrom
fix/tokens
Draft

fix: tokens#113
kah-seng wants to merge 1 commit intomainfrom
fix/tokens

Conversation

@kah-seng
Copy link
Member

@kah-seng kah-seng commented Feb 5, 2026

1. Local Storage Not Updated

Access tokens and refresh tokens are only saved to local storage on login, subsequent token refreshes do not update local storage.

Example: User refreshes to a new token and exits Overleaf, the next time he re-opens PaperDebugger, it uses the old refresh token.

Proposed solution: Update authStore whenever tokens are set.


2. Race Conditions When Refreshing

PaperDebugger often calls multiple endpoints at the same time, which results in a race condition if the token needs to be refreshed.

Example: v2/chats/models and v2/chats/conversations are called at the same time, and the access token needs refreshing, the refresh endpoint is called twice. In some occasions, the frontend uses the 2nd refresh token received which differs from the one stored in the backend. This can be easily reproduced by setting the JWT expiration in the backend to a very short time.

Proposed solution: Use a promise for refresh().



Unsure if this fixes the exact problem in #110

@kah-seng kah-seng linked an issue Feb 5, 2026 that may be closed by this pull request
Copy link
Member

@4ndrelim 4ndrelim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was investigating the bug too but saw you raised a PR before i did anything. So left some comments based on my udnerstanding. Seems like the right approach! Ill try to simulate some possible set-ups and test with ur fix.

}

setTokens(token: string, refreshToken: string): void {
useAuthStore.getState().setToken(token);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May i check if im understanding the situation right. This fix is for 401 error?

In particular, when we refresh due to 401 error from sending a request with expired tokens, we get the new generated tokens but this was never updated to auth-store (browser localStorage). And so, on the next session, e.g. page reload, auth-store loads stale tokens leading to 401 token expiry error?

token: resp.token,
refreshToken: resp.refreshToken,
});
if (this.refreshPromise) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice dedup logic. Yes this should address the multiple async calls to refresh, leading to multiple redundant token generation, and possible 401 bug across sessions.

This is actually rather tricky to test though since i think the bug is probabilistic? i believe for the current session, neither caller (your e.g. v2/chats/models and v2/chats/conversations) will bug out since auth-store uses last write valid token. It is only when caller_A and caller_B each calls refresh() and backend mongo receives a different set of token from auth-store.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Token expiration occurs more frequently than expected

2 participants