Tristan
Tristan
CCConvex Community
Created by Tristan on 9/9/2024 in #support-community
Race conditions with single use refresh tokens for Convex Auth
I'm trying to prototype refreshing Convex Auth tokens from my backend, to support server side rendering and data fetching. I'm able to do this by setting cookies instead of use local storage, but am struggling to avoid race conditions for the refresh token. There a few differen scenarious where multiple requests come it at the same time onto different servers. The servers notice the JWT is about to expire (I'm faking 10 seconds expire) and then call the signIn action with the refresh token. This often causes the user to log out because (I believe) the second refresh fails due to reusing the refresh token quickly. I've tried deduping the refresh calls, but this is not straightforward with multiple requests/servers/reloads so it's still flaky. Two questions: 1. Is it correct that the refresh token can only be used once, with no buffer in time? 2. With single use refresh tokens, is there a recommended approach to avoiding a race condition? There's a lot of things involved (multiple windows, multiple requests, multiple backend servers, etc) so coordination is hard.
1 replies
CCConvex Community
Created by Tristan on 9/7/2024 in #support-community
Remix and preloadQuery or alternatives
I'm trying to experiment with ways to avoid data loading flicker in Remix app. Is there a recommended approach to server side rendering / preloading? I tried putting preloadQuery from convex/nextjs in my remix component loader but get a bunch of errors. Any recommendations? My test code is:
import type { MetaFunction } from "@remix-run/node";
import { json, useLoaderData } from "@remix-run/react";
import { api } from "convex/_generated/api";
import { usePreloadedQuery } from "convex/react";

// Only available in NextJS package but trying to use it in Remix
import { preloadQuery } from "convex/nextjs";

// Remix data loader
export async function loader() {
// Runtime Typerror: Cannot destructure property 'ENV' of '__vite_ssr_import_1__.useLoaderData(...)' as it is undefined.
// Error: Environment variable NEXT_PUBLIC_CONVEX_URL is not set. (root.ts)
const tasks = await preloadQuery(api.tasks.get);
return json({ tasks });
}

export default function Index() {
const preloaded = useLoaderData<typeof loader>();
console.log(preloaded);
// Static TypeError: Argument of type 'JsonifyObject<Preloaded<FunctionReference<"query", "public", {}, any[], string | undefined>>>' is not assignable to parameter of type 'Preloaded<FunctionReference<"query">>'.
const tasks = usePreloadedQuery(preloaded.tasks);
return <div>{JSON.stringify(tasks)}</div>;
}
import type { MetaFunction } from "@remix-run/node";
import { json, useLoaderData } from "@remix-run/react";
import { api } from "convex/_generated/api";
import { usePreloadedQuery } from "convex/react";

// Only available in NextJS package but trying to use it in Remix
import { preloadQuery } from "convex/nextjs";

// Remix data loader
export async function loader() {
// Runtime Typerror: Cannot destructure property 'ENV' of '__vite_ssr_import_1__.useLoaderData(...)' as it is undefined.
// Error: Environment variable NEXT_PUBLIC_CONVEX_URL is not set. (root.ts)
const tasks = await preloadQuery(api.tasks.get);
return json({ tasks });
}

export default function Index() {
const preloaded = useLoaderData<typeof loader>();
console.log(preloaded);
// Static TypeError: Argument of type 'JsonifyObject<Preloaded<FunctionReference<"query", "public", {}, any[], string | undefined>>>' is not assignable to parameter of type 'Preloaded<FunctionReference<"query">>'.
const tasks = usePreloadedQuery(preloaded.tasks);
return <div>{JSON.stringify(tasks)}</div>;
}
8 replies