shadow_aya
shadow_aya14mo ago

Create user on Clerk registration

I would like to create an entry in my users table when Clerk auth finishes (for new users). I created a bumpUser function:
export const bumpUser = mutation({
async handler(ctx) {
const user = await ctx.auth.getUserIdentity();

if (!user) throw new Error("User not found");

const existingUser = await ctx.db
.query("users")
.withIndex("by_identity", q =>
q.eq("identity", user?.tokenIdentifier.split("|")[1])
)
.first();

if (existingUser) return;

await ctx.db
.insert("users", {
identity: user?.tokenIdentifier.split("|")[1],
...
});

},
})
export const bumpUser = mutation({
async handler(ctx) {
const user = await ctx.auth.getUserIdentity();

if (!user) throw new Error("User not found");

const existingUser = await ctx.db
.query("users")
.withIndex("by_identity", q =>
q.eq("identity", user?.tokenIdentifier.split("|")[1])
)
.first();

if (existingUser) return;

await ctx.db
.insert("users", {
identity: user?.tokenIdentifier.split("|")[1],
...
});

},
})
My intent was to trigger it via Clerk middleware, but I immediately realized that might not be a good idea: middleware.ts
const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export default authMiddleware({
publicRoutes: [
"/"
],
afterAuth: async (auth) => {
const token = await auth.getToken({
template: "convex"
});
if (!token) return;
convex.setAuth(token);
convex.mutation(api.accounts.bumpUser);
}
});

export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};
const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export default authMiddleware({
publicRoutes: [
"/"
],
afterAuth: async (auth) => {
const token = await auth.getToken({
template: "convex"
});
if (!token) return;
convex.setAuth(token);
convex.mutation(api.accounts.bumpUser);
}
});

export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};
- afterAuth fires multiple times. this is probably intentional on Clerk's side, but it's kind of stupid to be honest, they even combined the flow for all users who pass public pages and protected pages for those who are logged in. so far Convex queued the mutations well and didn't create duplicate users, so I assume I don't have to worry about this? - I can imagine the function blowing up even when two users request at the same time and token is mistakenly set. yes yes, this is very unlikely, but it looks like it could happen. I'm surprised the http client methods don't have an options argument where I could explicitly declare this token. you can take this part as a feature request, unless someone clarifies why that's not necessary should I instead somehow call the mutation on the client? do I make some adjustment? I am new to Clerk, and I've never done auth with Convex either. these abstractions are very simple, but can also be broken in a simple way. last thing I thought of while typing this - how's the type safety between Clerk and Convex user objects? (actually this might be a dumb question since Convex must be formatting the user object in its own way when verifying and typing it, unless there's also some missing keys for the various auth methods Convex can be used with) Thanks :PatTao: update looking into Clerk's webhooks instead, but I'm still interested about the token setting
1 Reply
ian
ian14mo ago
Templates
The backend application platform with everything you need to build your product.

Did you find this page helpful?