-
-
Notifications
You must be signed in to change notification settings - Fork 18
fix: prevent race condition in async token refresh #131
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
base: main
Are you sure you want to change the base?
Conversation
dc11250 to
9c556eb
Compare
| Promise.resolve().then(() => { | ||
| client.auth.getSession().catch(() => { | ||
| // Ignore errors - if session loading fails, the client is still usable | ||
| // and subsequent auth operations will handle the error appropriately | ||
| }); | ||
| }); |
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.
I'm a bit scared of this as it runs all the time when the server gets created, but without the ability to set cookies if that's needed
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.
@hf Yeah I agree, it's a slippery slope. I wonder if there's a better way to treat this, and not get that race condition issue.
|
@mandarini thanks for opening this, I'm running into this issue since I had to upgrade from Vite 5 => 7 in a SvelteKit project. Important Svelte and SvelteKit are moving really fast right now, since they have experimental support for async Svelte and SvelteKit remote functions. So SvelteKit users that want to keep dependencies up to day have to bump Vite to 7. Is there a workaround I could do to the recommended approach from the docs to sidestep the issue? The best I could come up with (with Claude's help) is: export const handle: Handle = async ({ event, resolve }) => {
// Creates a Supabase client specific to this server request.
// The Supabase client gets the Auth token from the request cookies.
event.locals.supabase = createServerClient(
PUBLIC_SUPABASE_URL,
PUBLIC_SUPABASE_ANON_KEY,
{
cookies: {
getAll: () => event.cookies.getAll(),
// SvelteKit requires cookie `path` to be explicity set
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) => {
event.cookies.set(name, value, { ...options, path: '/' });
});
},
},
},
);
// Workaround for supabase/ssr#131: trigger token refresh early
// before resolve() to prevent race condition with Vite 7
await event.locals.supabase.auth.getSession();
// Unlike `supabase.auth.getSession()`, which returns the session _without_
// validating the JWT, this function also calls `getUser()` to validate the
// JWT before returning the session.
event.locals.safeGetSession = async () => {
const {
data: { session },
} = await event.locals.supabase.auth.getSession();
// no session
if (!session) {
return { session: null, user: null };
}
const {
data: { user },
error,
} = await event.locals.supabase.auth.getUser();
// no jwt token
if (error) {
return { session: null, user: null };
}
return { session, user };
};
return resolve(event, {
filterSerializedResponseHeaders(name) {
// forward supabase headers
return name === 'content-range' || name === 'x-supabase-api-version';
},
});
}; |
What kind of change does this PR introduce?
Automatically initialize session on server client creation to trigger token refresh early in request lifecycle. This prevents race condition where refresh completes after response is sent, causing cookie errors. Also adds helpful error context before throwing if edge cases occur.
What is the current behavior?
Most possibly caused by token refresh.
What is the new behavior?
Initialize session to trigger token refresh early.