Web Dev Cody
Web Dev Cody14mo ago

Convex + Clerk, what userId should I be storing

Currently in my system I've been storing the clerk userId on all my table models as a string. I find this to cause a little friction because I don't have access to the v.id("users") all throughout my system by default, but the issue is my getUserIdentity() is the convex id, so if I wanted to lookup the real user._id in my system I'd end up having to do an extra query in all of my auth checks basically. Is there a recommended approach for what I'm doing? I'm starting to think storing clerk user id (external third party auth service) on all my tables wasn't the best move
12 Replies
jamwt
jamwt14mo ago
Yeah, in general I’d just use it exactly once—on your own users table. Then use the doc _.id from that convex table as your user id everywhere in the rest of your app.
ian
ian14mo ago
One pattern is to use customQuery / customMutation to make authenticated versions of query / mutation that does something like:
const authQuery = customQuery(query, customCtx((ctx) => ({ user: getUserOrThrow(ctx) })));
const authQuery = customQuery(query, customCtx((ctx) => ({ user: getUserOrThrow(ctx) })));
where getUserOrThrow does the auth -> identity -> user lookup by tokenIdentifier / clerk uid. then use it like:
export const getName = authQuery({
args: {},
handler: async (ctx, args) => {
console.log("userId: " + ctx.user._id);
return ctx.user.name;
}
});
export const getName = authQuery({
args: {},
handler: async (ctx, args) => {
console.log("userId: " + ctx.user._id);
return ctx.user.name;
}
});
More info: https://stack.convex.dev/custom-functions
Customizing serverless functions without middleware
Re-use code and centralize request handler definitions with discoverability and type safety and without the indirection of middleware or nesting of wr...
Web Dev Cody
Web Dev CodyOP14mo ago
ok that's nice I'll try that
Michal Srb
Michal Srb14mo ago
(The saas-starter I keep linking also uses Clerk for login, and follows the approach Jamie outlined: https://github.com/xixixao/saas-starter/ )
GitHub
GitHub - xixixao/saas-starter: Convex, Clerk, Next.js, Convex Ents
Convex, Clerk, Next.js, Convex Ents. Contribute to xixixao/saas-starter development by creating an account on GitHub.
Web Dev Cody
Web Dev CodyOP14mo ago
😂 ok ok I’ll take some time to review it all why do you use tokenIdentity instead of user.id? this is nice, it has a lot of ready to go functionality 😎
ian
ian14mo ago
tokenIdentity is also unique across identity providers - so if you added a non-clerk provider and they re-used similar IDs (maybe they use incrementing integers?) the tokenIdentifier would still be unique. It's just a concatenation of the issuer and the ID I believe
Web Dev Cody
Web Dev CodyOP14mo ago
nice I'll refactor to use that then not sure i understand actually so if someone logs in with google and facebook, wouldn't that be two different clerk users and ids?
ian
ian14mo ago
Yes. This is actually at a level higher than that. If you used clerk & auth0, they might issue user ids that overlap. Probably unlikely but the guarantee is that tokenIdentifier won’t have id collisions between auth providers
Web Dev Cody
Web Dev CodyOP13mo ago
what's the suggested approach again when you depend on webhooks to know when your clerk user is actually created? I got an error where the UI threw an error after registering because the auth in convex was defined, but the user wasn't created from the webhook yet
Michal Srb
Michal Srb13mo ago
I think in our template we wait on the server in the client: https://github.com/thomasballinger/convex-clerk-users-table/blob/main/src/main.tsx
GitHub
convex-clerk-users-table/src/main.tsx at main · thomasballinger/con...
Contribute to thomasballinger/convex-clerk-users-table development by creating an account on GitHub.
Abhishek
Abhishek13mo ago
In which file exactly ? Cant find the exact file
Web Dev Cody
Web Dev CodyOP13mo ago
@Abhishek the logic is in WaitForClerkUserData that component seems to query for the user info and prevent the page from rendering until it's defined

Did you find this page helpful?