Clerk and tRPC "protectedProcedures" on the server.

Hey everyone! I am trying to integrate Clerk into tRPC so I can create protectedProcedures (using create-t3-app). Essentially I need the "auth" object returned by getAuth to be part of the ctx. Now I got this working nicely for client components. However I am a bit stuck on how I would implement this for server components... I cannot see a way to pass the NextRequest object into createContext from the createCaller function. Any ideas?
5 Replies
Matvey
Matvey9mo ago
@clerk/nextjs provides auth() function, you can call it without any arguments and get the auth data
epsilon42
epsilon429mo ago
Not sure if this is what you're after but Theo's T3 stack tutorial uses Clerk for privateProcedure's: https://www.youtube.com/watch?v=YkOSUVzOAA4 Here's how he does it: https://github.com/t3dotgg/chirp/blob/main/src/server/api/trpc.ts
RobCipolla
RobCipollaOP9mo ago
Not quite... The method Theo uses in the video for adding the Clerk auth object to the ctx works a charm. However, I experimented with the Create T3 App App router and using tRPC on ther server. You know using import { api } from "@/trpc/server"; instead of import { api } from "@/trpc/react";. The problem is (if my understanding is correct) because Next server components don't have access to the Request object, I can't figure how to pass the auth object to the ctx when using tRPC on the server... (really not sure if this is making sense). I am looking to make sure these requests are authed:
const posts = await api.post.getAll()
const posts = await api.post.getAll()
These ones work fine:

const posts = api.post.getAll.useQuery();

const posts = api.post.getAll.useQuery();
I THINK it is because the server side api call for tRPC is created in server/trpc/api.ts where the context passed to it doesn't get access to the request object - which the clerk getAuth() method requires in order to create it's auth object.
/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const heads = new Headers(headers());
heads.set("x-trpc-source", "rsc");

return createTRPCContext({
headers: heads,
});
});

export const api = createCaller(createContext);
/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const heads = new Headers(headers());
heads.set("x-trpc-source", "rsc");

return createTRPCContext({
headers: heads,
});
});

export const api = createCaller(createContext);
where as I can pass the auth object to the clerk context in for client side components similar to the way Theo did in the tutorial.
RobCipolla
RobCipollaOP9mo ago
I suppose the question is... how do I get Clerk's auth object in the context when following this example from tRPC? https://trpc.io/docs/server/server-side-calls#context-with-middleware-example
Server Side Calls | tRPC
You may need to call your procedure(s) directly from the same server they're hosted in, createCallerFactory() can be used to achieve this. This is useful for server-side calls and for integration testing of your tRPC procedures.
RobCipolla
RobCipollaOP9mo ago
Figured it out. @Matvey was right. I can add Clerk's auth object to the server side context in /src/trpc/server.ts like so:
import "server-only";

import { headers } from "next/headers";
import { cache } from "react";

import { createCaller } from "@/server/api/root";
import { createTRPCContext } from "@/server/api/trpc";
import { auth } from "@clerk/nextjs";

/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const heads = new Headers(headers());
const authObject = auth();
return createTRPCContext({
headers: heads,
auth: authObject,
});
});

export const api = createCaller(createContext);
import "server-only";

import { headers } from "next/headers";
import { cache } from "react";

import { createCaller } from "@/server/api/root";
import { createTRPCContext } from "@/server/api/trpc";
import { auth } from "@clerk/nextjs";

/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const heads = new Headers(headers());
const authObject = auth();
return createTRPCContext({
headers: heads,
auth: authObject,
});
});

export const api = createCaller(createContext);
Want results from more Discord servers?
Add your server