Use Clerk `getAuth(req)` in a Zact server action

Is there a way to get the Next request object in a Zact server action. I require this to be able to get the current user using Clerk's getAuth function
Solution:
You gotta do action > server > client because action -> client doesn't support headers yet
Jump to solution
9 Replies
iukea
iukea13mo ago
Also interested in this
James Perkins
James Perkins13mo ago
If you use auth() we pull the headers... getAuth doesn't. Server actions which is what Zact is layering you can find how to use server actions right here. Using the App router specific built features. https://clerk.com/docs/nextjs/server-actions
Server Actions | Clerk
Learn how to use Clerk with Next.js Server Actions
ed.upton
ed.upton13mo ago
Ahh cheers, although I'm getting this error:
- error Error: Clerk: auth() and currentUser() are only supported in App Router (/app directory).
If you're using /pages, try getAuth() instead.
Original error: Error: Invariant: Method expects to have requestAsyncStorage, none available
at eval (./src/app/actions.ts:35:76)
- error Error: Clerk: auth() and currentUser() are only supported in App Router (/app directory).
If you're using /pages, try getAuth() instead.
Original error: Error: Invariant: Method expects to have requestAsyncStorage, none available
at eval (./src/app/actions.ts:35:76)
James Perkins
James Perkins13mo ago
You trying to use a server action directly in a client component?
ed.upton
ed.upton13mo ago
Yeah I'm calling it in a client component Do I need to pass down the action as a prop from my server components to client components like in the code example?
Solution
James Perkins
James Perkins13mo ago
You gotta do action > server > client because action -> client doesn't support headers yet
Etan
Etan13mo ago
sorry do you mind elaborating on this? i'm calling a server action from my client component but clerk is yelling at me with the same "auth() are only supported in app router"
James Perkins
James Perkins13mo ago
yup headers aren’t available in a client components so you have to do what’s described in our docs https://clerk.com/docs/nextjs/server-actions#with-client-components prop drill to your client component
Server Actions | Clerk
Learn how to use Clerk with Next.js Server Actions
Etan
Etan13mo ago
So i'm trying to create a context with zact server actions
import { auth } from "@clerk/nextjs"
import { zact } from "zact/server"
import z from "zod"

import { getDb } from "./db/get-db"

export type ContextType = {
auth: ReturnType<typeof auth>
db: ReturnType<typeof getDb>
}

export function withContext<InputType extends z.ZodTypeAny>(
inputType: InputType
) {
const ctx = {
auth: auth(),
db: getDb(),
}

return function <ResponseType extends any>(
action: (actionCtx: {
input: z.infer<InputType>
ctx: ContextType
}) => Promise<ResponseType>
) {
const validatedAction = zact(inputType)(async (input) => {
return action({ input, ctx })
})

return validatedAction
}
}
import { auth } from "@clerk/nextjs"
import { zact } from "zact/server"
import z from "zod"

import { getDb } from "./db/get-db"

export type ContextType = {
auth: ReturnType<typeof auth>
db: ReturnType<typeof getDb>
}

export function withContext<InputType extends z.ZodTypeAny>(
inputType: InputType
) {
const ctx = {
auth: auth(),
db: getDb(),
}

return function <ResponseType extends any>(
action: (actionCtx: {
input: z.infer<InputType>
ctx: ContextType
}) => Promise<ResponseType>
) {
const validatedAction = zact(inputType)(async (input) => {
return action({ input, ctx })
})

return validatedAction
}
}
And then i import this into my action
"use server"

import { auth } from "@clerk/nextjs"
import { z } from "zod"

import { users } from "../db/schema"
import { withContext } from "../with-context"

export const addResource = withContext(
z.object({
url: z.string(),
name: z.string(),
tags: z.array(z.string()),
})
)(async ({ input, ctx }) => {
const user = auth()
console.log(user)

const result = await ctx.db.select().from(users)
console.log("Got resource: ", input)
return { status: 1 }
})
"use server"

import { auth } from "@clerk/nextjs"
import { z } from "zod"

import { users } from "../db/schema"
import { withContext } from "../with-context"

export const addResource = withContext(
z.object({
url: z.string(),
name: z.string(),
tags: z.array(z.string()),
})
)(async ({ input, ctx }) => {
const user = auth()
console.log(user)

const result = await ctx.db.select().from(users)
console.log("Got resource: ", input)
return { status: 1 }
})
And then i prop drill the action into my client component and it still errors out. Is this not allowed?