Restrict Convex mutation to external Vercel functions, and block access from the client side
Hi,
Since Convex actions are very limited, many peopole prefer to use Vercel functions (espicially with their fluid runtime).
I need a Convex mutation which is restricted to external Vercel functions, but block access from the client side.
Currently on other Discord post I saw that you advised to send a shared secret as a parameter, but it's not considered secure since it can be accidently printed in logs... and it's a bad practice to send secret as a parameter.
I thought on something else:
In Vercel function - tell Clerk (using Clerk api-key) (my auth provider) to issue a JWT with custom claim (e.g. role=backend) and timeout of 60 seconds,
and then call the Convex mutation, and in the mutation check if the JWT contains the custom claim and allow/block access accordingly.
There are some docs in Clerk about this:
https://clerk.com/docs/backend-requests/custom-session-token
https://clerk.com/docs/backend-requests/jwt-templates
Can you please write an example for how to do it in such secure way?
I'm struggling with this, and I think many folks who uses next.js with Vercel functions will benefit from this example.
Thanks
Backend Requests: Customize your session token
Learn how to customize the session token that is generated for you by Clerk.
Backend Requests: JWT templates
Learn how to create custom JWT templates to generate JSON Web Tokens with Clerk.
6 Replies
Thanks for posting in <#1088161997662724167>.
Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets.
- Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.)
- Use search.convex.dev to search Docs, Stack, and Discord all at once.
- Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI.
- Avoid tagging staff unless specifically instructed.
Thank you!
I haven't tried this, but you should be able to set up multiple clerk jwt templates by adding more entries to the
convex/auth.config.ts
array, you'd just need to set a different audience for each, maybe this one can be clerk-backend-only
. And I believe the custom claim will then be present on the identity object from ctx.auth.getUserIdentity
.
Specify the correct jwt template when you get the token from clerk, also
Hopefully that works, curious to hear if it doesI tried, but didn't manage to do it easily, and since I just wanted to test Convex as POC to see if it fit for us..., I gave up on this...
If the Convex team can write example for this it would be great!
You can make an internalMutation, and then wrap it in an httpAction, and then call that from your vercel function as follows:
One issue with this is that a simple mutation ends up being 2 function calls for billing purposes (the http action and the internal mutation). Ideally, there would be a way to mutate the database in actions or httpActions, but i understand this is not possible (and maybe not desirable).
They're specifically looking for an alternative to a shared secret
Currently on other Discord post I saw that you advised to send a shared secret as a parameter, but it's not considered secure since it can be accidently printed in logs... and it's a bad practice to send secret as a parameter.
Understood. We also did this using the package to mint a custom token with limited expiry and encrypted payload... which we can invoke in a vercel API route / server action using the fetchMutation. The pairs are: i imagine if one wanted to not have token be in the args (because it might appear in logs), one can convert this to an httpAction and put the token in the header (although that might also appear in logs).