Clerk authenticates, Convex do user management and features. Convex stores user data
Objective
Minimal Clerk Side: Use Clerk primarily for user authentication.
Convex for User Data Management: Store and manage all user-related data within Convex.
Key Steps
Set Up Convex Schema: Define the user schema in Convex to store necessary user data fields.
Use Convex for Data Operations: Implement queries and mutations in Convex to manage user data, ensuring that all relevant user information is stored in Convex so I can process.
I won't create custom flows with Clerk but I will build custom flows with my own database(fetch from my own DB, since storing the same data with Clerk which means similar thing) and backend but Clerk securely handles authentication
E.g. I won't use useUser(); from Clerk but useMyDatabaseUser();
In the philosophy of store minimal in Clerk. Isn't it better to manage such features¹ in Convex rather than Clerk?
¹:
E.g. features² probably something we wouldn't have in Convex and Clerk has some characteristics on them
²:
Feel free to share some insights!
My approach is copying the UserJSON to my database. Manage the user data from my databases User object and sync when it changes
So I will never use useUser() and as I said, useMyDatabaseUser()
14 Replies
Clerk support has replied me as this:
This message has made me doubt if I'm doing something wrong
You're not, Clerk wants people to use Clerk all the way, that's all. A lot of folks don't want all of their data in Convex, but have to keep user source of truth in a separate service. I think the message here is Clerk isn't going to help you use Clerk less.
Which is fair.
But the community here will help 👍
Syncing user data when it changes is what most folks in your position are doing. Have you run into issues? Or any specific concerns?
I'm also assuming you know about Convex Auth and are choosing to go with Clerk for features that Convex Auth doesn't provide.
It wasn't a thing when I started I guess and I don't know much about Convex Auth.
First of all, thank you so much. You can't imagine how helpful any response is.
I currently have webhook sync
Clerk -> Convex
. I don't know how much should Convex include or should be whole UserJSON
of Clerk.
It was only externalId
and firstName
I guess. Now I think I should have majority of the UserJSON that Clerk sends to Convex. Then can manage the user primarily on Convex rather than Clerk. But the thing is, it will keep handling MFA, etc. and it has some features such as banned, lockout etc. well, how will it work together what should be in Convex, and Clerk. Will it work etc. I'm very confused and my ideas very inconsistent
So sorry if my words doesn't make any sense
Or will I manage users password on Convex or Clerk? What about email. Let's say I build device revocation, how will Convex tell Clerk to revocate the device?
https://clerk.com/docs/references/javascript/user/userIn that case:
- sounds like you want functionality that's beyond what Convex Auth has, so staying with Clerk makes sense
- you do want to let Clerk handle passwords, don't store them in Convex at all, same for any other auth artifact (tokens, etc). If you're using Clerk, use it all the way for the authentication process specifically.
- however, any user data that you want to access in your app, including on the backend, syncing Clerk data back to Convex via webhook is the way to go
- have not looked into revocation at all, does Clerk support that?
It does if purchased the required extension
As you know, Clerk works well with their own UI and I want the same functioning but on my database and without its security intelligence
Understood I should not store password. Well, won't I need to access attributes such as
phoneNumber
if verified: boolean
, or 2FA enabled(e.g. user menu gives alert to enable it for better security)
It is just too comprehensive and if I think about an architecture, I think about some scenarios and I don't know how should it be.
Convex team has told me I would most likely want some of the features to be on Convex side such as enhanced roles and some other
And my objective is to have the same level of functionality and have at least majority on Convex and be able to process directly from Convex
Those features all sound nice, and a good use of Clerk IMO. The one that stands out to me as better in Convex state is "Enhanced roles" - I bet you'll want your "who has access to what and which organization are they in" to be in your Convex DB, not Clerk metadata. Make sense? You would be building all of the device tracking, revocation, etc yourself. Convex doesn't have any out-of-the-box features for these things, so if you want them soon I'd start with Clerk, and if you later want to build a more custom version of them you can build them from scratch later (or maybe find some library / component that works with Convex) re: performance, your user queries will be alongside your other Convex data, so it'll be faster in that regard. However, there is a bit of a waterfall of requests: Clerk says you're signed in and the client gets the token Convex sends the token up, then calls something like storeUser and a user is created / verified that it exists Your functions that depend on auth runI sent these quotes if it helps to understand the benefits and motivation
Yeah that all makes sense. I agree w/ the quote, authorization/roles I would keep in your app and stored in Convex, no need to put that in Clerk. As far as accessing phone number, verified, etc. that's part of the state that you would keep synced between Clerk and Convex.
So I should keep that in my Convex user table. Then how much from the UserJSON of Clerk?
last_active_at: number | null;
banned: boolean;
Should I ignore these better-to-be-in-Convex Clerk's attributes or keep them in sync(likely)?
Another example, Clerk has external_accounts: ExternalAccountJSON[];
Should I have this on my Convex user table as well?
I thought about dual-sided sync as well. I would sync Clerk ➡️ Convex with webhook which I already have that setup and for the Convex ➡️ Clerk I would do API call to Clerk(I don't know how and if possible). Or do I use Clerk's functions such as createBackupCode()
from Clerk to update it on Clerk as well?
If that's something I probably won't need and I shouldn't be worried about. I am okay to not access it or hybridly use Clerk functions on these specific cases if I should use
I hope not bothering you. Thank you really so much 🫶No bother, this is what support forum is for 👍
Two approaches:
1. sync only the data you need to access within your application logic
2. sync everything just in case you need it
My own approach, for whatever it's worth, is to shape my own user data (in Convex) independent of Clerk's (or any provider's) chosen format. So I have fields in my users table that represent what I need and want to store for my user, regardless of how I'm doing auth. Some of those values I get from Clerk, some I get through my own UI and forms.
Are you using their components in your UI by chance?
I am using Clerk's UIs completely at the moment. The goal is using custom UIs and custom user settings
Eventually or you're working on replacing them now
Either way, though, syncing back to Convex and using the data in Convex will work for you
I don't know if you've experienced that not being the case in your usage
Sounds good. I like the 1. Maybe I won't need whole user as same as what I receive from Clerk.
In the user settings, I will update the Convex data and the sync system will send the updated convex user to Clerk anyways. No matter what, Convex data is the single source of truth and hopefully there won't occur weird bugs such as, in the user settings, user is alerted to verify phone number, user verifies on Clerk and Convex still thinks it is not verified etc. but it is pretty unlikely I guess and if occurs, there will be a simple way to fix it like a normal problem.
Well, how do Convex tell Clerk to do something like revocating the user(I guess basically it is ending a session and I'd get the session Id by Convex(which gets from the JWT token that Clerk gives) and end with Clerk's function)and how do Convex send the updated user, maybe I got dumb with the overwhelm but in the case user table attribute names are going to be different than Clerk, at least not identical. How the Clerk will get sync with the user data with different attribute names?
Oh makes sense
Probably making the table names identical will just work to replace(upsert)?
Not sure what you mean here, can you explain
I just realized it was an unnecessary concern. For example, you see the
phoneNumbers
array there in the Convex database. And assume phoneNumbers
attribute is named arrayPhoneNumbers
in Clerk. I asked how Clerk can understand received phoneNumbers
attribute value should be replaced to arrayPhoneNumbers
but probably there is not such reason so the question was wrong. I believe I should just keep the names same.Yeah that works