How to Include Clerk Auth Headers in Server-side Fetch
Unanswered
Giant Angora posted this in #help-forum

Giant AngoraOP
I’m using Next.js (App Router) with TanStack Query for prefetching data in a Server Component, and I’m also using Clerk for authentication.
The issue is that when I fetch data from my protected API route inside a Server Component, the request doesn’t include authentication headers automatically. However, when I make the API route public, everything works fine.
Here’s my setup:
🔹 What I’m Doing
- Prefetching data on the server using queryClient.prefetchQuery().
- Fetching from a protected API route that requires authentication.
- Using Clerk for authentication.
🔹 Issue
- Server-side fetch does not include the Clerk session (JWT or cookies).
- The API route rejects the request due to missing authentication.
- If I remove authentication (make the route public), it works fine.
The issue is that when I fetch data from my protected API route inside a Server Component, the request doesn’t include authentication headers automatically. However, when I make the API route public, everything works fine.
Here’s my setup:
🔹 What I’m Doing
- Prefetching data on the server using queryClient.prefetchQuery().
- Fetching from a protected API route that requires authentication.
- Using Clerk for authentication.
🔹 Issue
- Server-side fetch does not include the Clerk session (JWT or cookies).
- The API route rejects the request due to missing authentication.
- If I remove authentication (make the route public), it works fine.
export default async function ProductsPage(props: ProductsPageProps) {
const { name } = await props.searchParams;
const isFiltered = !!name;
const queryClient = getQueryClient();
void queryClient.prefetchQuery(productsOptions);
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<main className="p-5 md:px-8">
<div className="mb-5 flex gap-3">
<DataTableHeading
heading="Products"
queryKey={queryKeys.PRODUCTS}
/>
</div>
<SwrDataTable
columns={columns}
queryKey={queryKeys.PRODUCTS}
route="products"
isFiltered={isFiltered}
/>
</main>
</HydrationBoundary>
);
}
11 Replies

this is wrong
you don't fetch your own api routes in server components

Giant AngoraOP
yeah i know
clerk provides a server side function which you can use to check current auth status and directly query db

Giant AngoraOP
i know i can directly query db... but how can i make it work with tanstack query
i use drizzle and fetch directly in server component... what this method arise problem is that when i refresh route with router.refresh, i cannot show any loading indicator
i decided to use tanstack query

Giant AngoraOP
i made it work bro
export const PreloadSwrDataTable = <TData extends { id: number }>(
props: PreloadSwrDataTableProps<TData>,
) => {
const { columns, isFiltered, promise, queryKey, route } = props;
const queryClient = getQueryClient();
return (
<React.Suspense
fallback={
<div className="border-t border-border py-10">
<Loader2Icon
size={50}
className="mx-auto animate-spin text-muted-foreground"
/>
</div>
}
>
<Awaited promise={promise}>
{() => (
<HydrationBoundary state={dehydrate(queryClient)}>
<SwrDataTable
columns={columns}
queryKey={queryKey}
route={route}
isFiltered={isFiltered}
/>
</HydrationBoundary>
)}
</Awaited>
</React.Suspense>
);
};
i fetched directly instead of using own api route