Oren
Oren5mo ago

How to get user details in server component

How can I get user details with convex auth on nextjs server component? I have a query that works when used in client side with useQuery but it doesn't work with fetchQuery
7 Replies
Oren
OrenOP5mo ago
export const currentUser = query({
args: {},
handler: async (ctx) => {
const userId = await auth.getUserId(ctx);
let user = null;

if (userId) {
user = await ctx.db.get(userId);
}

const identity = await ctx.auth.getUserIdentity();

return { identity, user,};
},
});
export const currentUser = query({
args: {},
handler: async (ctx) => {
const userId = await auth.getUserId(ctx);
let user = null;

if (userId) {
user = await ctx.db.get(userId);
}

const identity = await ctx.auth.getUserIdentity();

return { identity, user,};
},
});
^ works with client component/page
const test = useQuery(api.messages.currentUser);
const test = useQuery(api.messages.currentUser);
doesn't work with server component/page (getting null/undefined)
const test = fetchQuery(api.messages.currentUser);
const test = fetchQuery(api.messages.currentUser);
got it working with; 1) Get token in server session and pass to fetchQuery 2) Parse token and get userId 3) Use userId I wonder if this is a bad practice?
export const currentUser = query({
args: { token: v.optional(v.string()) },
handler: async (ctx, { token }) => {
let userId = await auth.getUserId(ctx);

if (token && !userId) {
const arrayToken = token.split(".");
const tokenPayload = JSON.parse(atob(arrayToken[1]));
userId = tokenPayload.sub.split("|")[0];
}

let user = null;
let identity = null;

if (userId) {
user = await ctx.db.get(userId);
}

identity = await ctx.auth.getUserIdentity();

return { identity, user };
},
});
export const currentUser = query({
args: { token: v.optional(v.string()) },
handler: async (ctx, { token }) => {
let userId = await auth.getUserId(ctx);

if (token && !userId) {
const arrayToken = token.split(".");
const tokenPayload = JSON.parse(atob(arrayToken[1]));
userId = tokenPayload.sub.split("|")[0];
}

let user = null;
let identity = null;

if (userId) {
user = await ctx.db.get(userId);
}

identity = await ctx.auth.getUserIdentity();

return { identity, user };
},
});
this is how fetchQuery looks like
const test = await fetchQuery(api.messages.currentUser, {
token: convexAuthNextjsToken(),
});
const test = await fetchQuery(api.messages.currentUser, {
token: convexAuthNextjsToken(),
});
^ works nicely on production as well 🔥 ehhhh signout is not working
erquhart
erquhart5mo ago
I don't know if this will impact you or not, but looks like an update is out: https://discord.com/channels/1019350475847499849/1019350478817079338/1273479617788903518
Oren
OrenOP5mo ago
I did update/no changes seems like this is happening to multiple users https://discord.com/channels/1019350475847499849/1273008614000427099
Michal Srb
Michal Srb5mo ago
@Oren for your original question the code is
const test = await fetchQuery(api.messages.currentUser, {}, {
token: convexAuthNextjsToken(),
});
const test = await fetchQuery(api.messages.currentUser, {}, {
token: convexAuthNextjsToken(),
});
Notice the extra second param. see https://labs.convex.dev/auth/authz/nextjs#preloading-and-loading-data
Server-side authentication in Next.js - Convex Auth
Authentication library for your Convex backend
Oren
OrenOP5mo ago
that is amazing. You kept me with convex tbh. I will upgrade and move from supabase 👍
Martha Lucr King Jr
Hey, i'm using clerk for auth, what would it look like for me?
erquhart
erquhart3mo ago
Just going on docs, it looks like you want this: https://clerk.com/docs/references/nextjs/auth#use-auth-to-retrieve-user-id That object it returns with userId is an auth object, it also has a getToken() method: https://clerk.com/docs/references/nextjs/auth-object#auth-object-properties

Did you find this page helpful?