How do you get the issuer for a new user account from Clerk webhooks?
I followed this documentation: https://docs.convex.dev/auth/database-auth#set-up-webhooks
and was able to use a Clerk webhook in order to automatically insert a document in
users
Convex table.
But, I'm trying to adhere to the pattern where the users
table has a tokenIdentifier
column.
The problem is that I don't see a way to get the issuer value from the Clerk webhook.Storing Users in the Convex Database | Convex Developer Hub
_If you're using Convex Auth the user information
13 Replies
Observed Behavior:
1) I see in this documentation: https://docs.convex.dev/auth/database-auth#optional-users-table-schema-1
that there is a column
Anyway, I want to use a
externalId
. I find that to be an unusual suggestion. It's conceptually correct that that column is an external identifier, but usually the Convex community recommends to use a tokenIdentifier
column in order to make it easy to migrate to another auth solution in the future.Anyway, I want to use a
tokenIdentifier
column, constructed as [issuer]|[subject].
2) Later, the documentation https://docs.convex.dev/auth/database-auth#mutations-for-upserting-and-deleting-users
has this function upsertFromClerk which is what inserts the document.
Here, the externalId is getting assigned the value of subject. But I instead need the value of [issuer]|[subject] to get assigned.
Storing Users in the Convex Database | Convex Developer Hub
_If you're using Convex Auth the user information
3) If I command_click into UserJSON, I don't see anything pertaining to the notion of an issuer. I'm referring to the issuer and subject defined in UserIdentity https://docs.convex.dev/api/interfaces/server.UserIdentity
Interface: UserIdentity | Convex Developer Hub
server.UserIdentity
4) And if I go to my Clerk dashboard, go to Webhooks, go to Logs, click the relevant user.created Event Type, the "Message content" does not have any properties that contain what would be the value for issuer.
5) Since my
users
table uses tokenIdentifier
, I replaced externalId
column with tokenIdentifier
in the various users.ts functions.
But since externalId
was only getting assigned the subject
, my user document is being inserted without an issuer in the tokenIdentifier
column.
Possible resolution:
How would you recommend that I proceed? I still want to adhere to the
tokenIdentifer
column design. Should I maintain environmental variables or constants in my Next.js project that holds the issuer
for each environment?
Perhaps there is a way to add a ctx.auth.getUserIdentity() call to Clerk inside the HTTP action:
in order to get the tokenIdentifer. But it seems inefficient and error-prone to receive an event from a Clerk webhook, only to call Clerk again with ctx.auth.getUserIdentity(). And I don't know how the HTTP action would have the context about who the user is.Is the issuer just the
domain
set in the providers list in auth.config.ts
?
tokenIdentifier
is a safeguard against multiple providers using the same ID.yes it is
so if you have the domain set from an env variable there already, you can use that like
${process.env.CLERK_ISSUER_URL}|${data.id}
right? or are you hard-coding the issuer in auth.config.ts?Yeah, that's fine. I will just do that
I thought it would be a problem once I do preview environments, which I haven't really explored yet
you can set default env vars for preview environments
If you find over time that
tokenIdentifier
is not the best for you - maybe you prefer to use the id from clerk or track the github user id or something, you can always do a migration to another field, or have tokenIdentifier
be of a different format. And if you do use http actions and set the JWT as the bearer token, you can use ctx.auth inside of those actions too, in case that wasn't clear. but I don't think clerk webhooks set that header when they call overRight, Clerk's user.created webhook doesn't send that issuer info.
Okay, sounds good. I'll proceed with using the environment variable.
I'm trying to follow Convex's recommendations very closely so I minimize the chances I need to do big migrations in the future, espeically for user data. The docs for setting up Clerk webhooks has a column externalId, so I needed to think through how to make it work with tokenIdentifier
If the intention was that column hold the subject, maybe subject would have been better just to clarify that this column is intended to hold Convex API's userIdentity.subject
Otherwise, I thought these was really good documentation: https://docs.convex.dev/auth/database-auth
Storing Users in the Convex Database | Convex Developer Hub
_If you're using Convex Auth the user information
Clerk has a corresponding documentation for Convex, but it was harder to understand what was going on. I started with the Clerk docs. Having both is nice