Skip to content

get-convex/workos-convex-nextjs-testbed

Repository files navigation

Convex + Next.js + WorkOS AuthKit Testbed App

See @workos/template-convex-nextjs-authkit for the recommended Convex + AuthKit template; this repo is for discussion and testing.

link to example hosted on Vercel

To get this running locally follow the instructions at the repo above.

Patterns shown

Both views use eagerAuth: true in middleware.ts to make an access token available immediately on render.

Client-side auth

The root route / does Convex authentication client-side, similar to what is used in a zero-backend React SPA.

During SSR no content renders, regardless of whether the user is logged in.

After hydration the client requests a JWT if AuthKit says the user is logged in.

  • middleware.ts lists '/' as an "unauthenticated path" so AuthKit middleware will allow this route to render for logged-out users
  • app/page.tsx uses <Authenticated>, <Unauthenticated>, and <AuthLoading> wrapper component to load different content and, critically, to wait to load content until the Convex client has a JWT

Server-rendering data that requires auth

/server requires auth and renders authenticated content immediately.

During SSR the user must be authenticated and authenticated queries can be made.

After hydration a new JWT is requested and queries start to run once a JWT is received (due to expectAuth: true).

  • middleware.ts causes '/server' to only render for logged-in users
  • app/page.tsx calls withAuth() which opts this route out of static rendering and into dynamic rendering by accessing cookies in its implementation. This page does not use <Authenticated> to prevent authenticated queries from running.

Repros of things that don't work

Not using <Authenticated>

/server doesn't use the <Authenticated> component, so if an auth refresh ever fails its out of luck: the queries will render anyway.

Reproducing this is inconsistent.


Ideas

Using the <Authenticated> wrapper components on SSR'd pages

Today <Authenticated> content never runs during SSR, during SSR the auth state is always "unauthenticated" or "loading." If <Authenticated> could be used during SSR then

  • server pages could take advantage of better logged-out behavior (unmount instead of query errors)
  • there'd be less flashes

Not specifying { expectAuth: true }

Specifying { expectAuth: true } requires different code for different routes and unfortunately blocks all queries, not just authed ones.

It also doesn't work as well as <Authenticated> for switching between different auth token fetchers (see get-convex/convex-js#82).

  • could we determine this based on some other list of authed routes, like in middleware?
  • should a special argument to useQuery() hooks annotate whether they require auth? Opt-int could go the other way. (see get-convex/convex-js#69)
  • (deeper convex changes) to make the above work better could public functions declare their auth needs with typed middleware?