T
TanStack2mo ago
optimistic-gold

Getting userId in server function

Hello, First of all, thank you for this amazing framework! I’m getting more and more hooked on it every day. I’ve been using Clerk for authentication and exploring how it integrates with Tanstack Start. Currently, I’m protecting my server functions with an authentication middleware like this:
import { createMiddleware } from "@tanstack/react-start";
import { auth } from "@clerk/tanstack-react-start/server";

export const authMiddleware = createMiddleware({ type: "function" }).server(
async ({ next }) => {
const { isAuthenticated, userId } = await auth();

if (!isAuthenticated || !userId) {
throw new Response("Unauthorized", {
status: 401,
});
}
const result = await next();

return result;
}
);
import { createMiddleware } from "@tanstack/react-start";
import { auth } from "@clerk/tanstack-react-start/server";

export const authMiddleware = createMiddleware({ type: "function" }).server(
async ({ next }) => {
const { isAuthenticated, userId } = await auth();

if (!isAuthenticated || !userId) {
throw new Response("Unauthorized", {
status: 401,
});
}
const result = await next();

return result;
}
);
Then, I apply the middleware to my server function to protect access:
export const createBook = createServerFn({ method: "POST" })
.middleware([authMiddleware])
.inputValidator(createBookSchema)
.handler(async ({ data }) => {
// rest of the logic
});
export const createBook = createServerFn({ method: "POST" })
.middleware([authMiddleware])
.inputValidator(createBookSchema)
.handler(async ({ data }) => {
// rest of the logic
});
Inside the server function handler, I need to access the userId. I can retrieve it with the Clerk backend library like this:
import { auth } from "@clerk/tanstack-react-start/server";

const { userId } = await auth();
import { auth } from "@clerk/tanstack-react-start/server";

const { userId } = await auth();
Alternatively, I could return it through the middleware context:
return await next({ context: { userId } })
return await next({ context: { userId } })
However the “context” approach feels a bit insecure to me. I’m not entirely sure how the context works under the hood, but I’m concerned that an authenticated user might somehow manipulate the userId and create records on behalf of someone else. Could someone clarify whether this concern is valid or if the context is safe in this case? Thanks!
2 Replies
fascinating-indigo
fascinating-indigo2mo ago
However the “context” approach feels a bit insecure to me.
there is nothing to be afraid of here. middleware just means that a function will be called before the server function handler and you can pass stuff from it to the server function pseudocode
function startHandler(request) {
const middlewareResult = await middleware(request)
const serverFnHandlerResult = await serverFnHandler(request, middlewareResult)
return serverFnHandlerResult
}
function startHandler(request) {
const middlewareResult = await middleware(request)
const serverFnHandlerResult = await serverFnHandler(request, middlewareResult)
return serverFnHandlerResult
}
if you use a client middleware however, then the context originating from it must be validated so no client side modification happened
optimistic-gold
optimistic-goldOP2mo ago
thank you @Manuel Schiller!

Did you find this page helpful?