- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: resolve & reset deferred upon refresh error #339
Conversation
If error is not an AuthError _callRefrehToken throws the error This commit ads a test and fix for this scenario.
src/GoTrueClient.ts
Outdated
@@ -37,6 +37,14 @@ import type { | |||
|
|||
polyfillGlobalThis() // Make "globalThis" available | |||
|
|||
type CallRefreshTokenResult = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type is solely used in private methods and properties. Not sure if it nevertheless should go to lib/types.ts
? Both is fine for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah let's put this in lib/types.ts
to keep things consistent 😄
): Promise<CallRefreshTokenResult> { | ||
// refreshing is already in progress | ||
if (this.refreshingDeferred) { | ||
return this.refreshingDeferred.promise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved that out of the try block and removed the await
. Otherwise a rejection would fall into catch
and finally
multiple times. As _callRefreshToken
throws non AuthErorr
's that should be the expected behavior.
test/GoTrueClient.test.ts
Outdated
@@ -1,4 +1,5 @@ | |||
import { OpenIDConnectCredentials } from '../src' | |||
import { AuthError } from '../src/lib/errors'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errors are not exported by the library. Would it make sense to export them so a consumer can import errors and compare them with instanceof AuthError
or isAuthError(error)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point – we definitely should at least be exporting isAuthError()
Thank you for looking into this. This fixes the problem for me.
For reference here is an earlier implementation of shared token refreshes, where these two points are addressed https://github.com/supabase/gotrue-js/pull/203/files#diff-3522461172efd6058d6b8da62fc2d30d8b524d2b64894ea2c67218c52f7fdff5 |
Regarding @wattroll's points:
The implementation in #203 does not protect from race condition.
This indeed is a potential issue. But the solution to have a promise/deferred for each token would shift the race condition down to My intention for this PR is solely to fix a Bug (see #334) introduced with #285. Probably it makes sense to open a new Issue with @wattroll 's points to discuss them further? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @pixtron! This looks great!
Would you mind running prettier (npm run format
) on your code and moving CallRefreshTokenResult
to lib/types.ts
, then I'll merge this in.
Thanks for adding tests too!
Moved Prettier changed this line const { session: session3, error: error3 } = await authWithSession._callRefreshToken(session?.refresh_token) to 3 lines, which resulted in the TS error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making those changes.
I agree that the non-null assertion is fine there.
Cheers!
🎉 This PR is included in version 1.23.0-next.12 🎉 The release is available on: Your semantic-release bot 📦🚀 |
🎉 This PR is included in version 2.0.0-rc.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
What kind of change does this PR introduce?
Bug fix
What is the current behavior?
Currently
refreshingDeferred
does not get resolved/rejected upon error. Also the deferred does not get reset to null during an error. See #334What is the new behavior?
The deferred gets resolved upon AuthError and rejected upon other errors, and finally reset to null. Like this the deferred Promise behaves like the Promise returned by
_callRefreshToken
itself.Additional context
Closes #334