Closed simonjcarr closed 4 months ago
I have found a solution. There is a __session cookie set that contains the clerk JWT. This can be verified with @clerk/clerk-sdk-node
Here is a function I have setup on the server side, that takes an event from one of my API's, validates the token and returns both the clerk userId (JWT sub) and the local user I have in my database for each clerk user.
import { verifyToken } from '@clerk/clerk-sdk-node'
import { db } from '~/server/db';
import { H3Event } from 'h3'
import { eq } from 'drizzle-orm';
import { users } from '../db/schema';
export default async function (event: H3Event) {
const cookies = parseCookies(event)
const key = process.env.CLERK_SECRET_KEY || '';
try {
const payload = await verifyToken(cookies.__session, { secretKey: key });
const dbUser = await db.query.users.findFirst({
where: eq(users.clerkId, payload.sub || ''),
})
return { clerkId: payload.sub, userId: dbUser?.id }
} catch (error) {
throw new Error('Auth Token is not valid')
}
}
Now in my API routes, I can simply do this
import validateToken from '~/server/auth/validateToken'
export default defineEventHandler(async (event) => {
const { clerkId, userId } = await validateToken(event)
....
})
Hopefully this will help someone else out and perhaps could be added to the Nuxt Guide
Hey! If you're using Nuxt, you might be interested in this template that uses vue-clerk and h3-clerk - https://github.com/wobsoriano/nuxt-clerk-template
See how the plugin was installed here - supports SSR!
Then you can do this in your route middleware
import { useAuth } from 'vue-clerk'
export default defineNuxtRouteMiddleware((to) => {
const { isSignedIn } = useAuth()
const protectedPages = ['dashboard', 'organization']
const publicPages = ['sign-in', 'sign-up']
const isProtectedPage = protectedPages.includes(to.name as string)
const isPublicPage = publicPages.includes(to.name as string)
if (isSignedIn.value && isPublicPage)
return navigateTo('/dashboard')
if (!isSignedIn.value && isProtectedPage)
return navigateTo('/sign-in')
})
Hi @wobsoriano I am already using that middleware and protecting my pages with it, but I don't see how that gives me access to the clerk user in a function running on the server?
Oh my bad, I actually thought the code you posted are route middlewares! Im blind lol
Well in that case, if you're using h3-clerk
, you can use the auth
context to access the user:
import { clerkClient, getAuth } from 'h3-clerk'
export default eventHandler((event) => {
const auth = getAuth(event)
// or just get it directly from `event.context.auth`
if (!auth.userId) {
setResponseStatus(event, 403)
return
}
return clerkClient.users.getUser(auth.userId)
})
Thank you
Thanks for this library I love that I can now use Clerk in Nuxt.
My only issue at the moment is that I am only able to access the Clerk user on the front end with
useUser
.When I use a useFetch to pull data from the backend, I need to be able to access user direct from Clerk so I can verify the user before sending data back to the front end.
With the following code, I get the error
This composable can only be used when the Vue Clerk plugin is installed
Update: I notice from another issue that is now closed a user was told that vue-clerk only works on the client. If this is the case how do we secure a backend in nuxt. I can not trust the front end to send a userId to the backend, that could be faked by a malicious actor.
I am assuming I am missing something here that other people have already solved, but how do I get secure access to the clerk user on the backend?