#Betterauth / User table linking
9 messages · Page 1 of 1 (latest)
Hi @pallid gull. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
When using Better Auth with Convex, the recommended approach for linking your app's user table to the Better Auth user table is to store the Better Auth user's ID (commonly called authId) in your app's user table. This is now the preferred pattern, as tracking your app's user ID in the Better Auth table (via user.userId) is deprecated and will be removed in future releases.
How to Link the Tables
- Add an
authIdfield to your app's user table. This field will store the Better Auth user's_id. - In your user creation trigger (onCreate), insert a new user in your app's table and set the
authIdtoauthUser._id. TheauthUserobject passed to the trigger will contain the_idfield.
Example:
export const authComponent = createClient<DataModel>(components.betterAuth, {
authFunctions,
triggers: {
user: {
onCreate: async (ctx, authUser) => {
await ctx.db.insert("users", {
email: authUser.email,
authId: authUser._id, // Link to Better Auth user
});
},
},
},
});
- Update your queries to use the
authIdfield when looking up users.
Example:
const user = await ctx.db
.query("users")
.withIndex("authId", (q) => q.eq("authId", authUser._id))
.unique();
Why doesn't onCreateUser have an ID?
The onCreateUser callback (from older versions) did not provide the Better Auth user ID because the user record had not yet been created. With the new triggers system, the onCreate trigger receives the full authUser object, including _id, after the user is created, which solves this problem and is the recommended approach going forward.
Summary:
Store the Better Auth user's _id as authId in your app's user table during the onCreate trigger. This is the current best practice and is well-supported by the latest versions of Better Auth and Convex. For more details and migration steps, see the migration guide and triggers documentation.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@pallid gull Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Thanks @charred wadi . I have updated my project but the _id field is still throwing a type error on the object returned in the onCreateUser hook. Is this a known error at the moment? --> Property '_id' does not exist on type '{ image?: string | null | undefined; twoFactorEnabled?: boolean | null | undefined; isAnonymous?: boolean | null | undefined; username?: string | null | undefined; displayUsername?: string | ... 1 more ... | undefined; ... 12 more ...; updatedAt: number; }'.ts(
Let me check the knowledge base for you again. One moment! :books:
Yes, this is a known issue that has come up in the community. The problem is that in older versions of Better Auth, the onCreateUser callback did not provide the Better Auth user’s _id field, because the user record had not yet been created at the time the callback was invoked. As a result, the object passed to onCreateUser does not include _id, and TypeScript will throw a type error if you try to access it.
The recommended solution is to migrate to the new triggers system, where the onCreate trigger receives the full authUser object, including the _id field, after the user is created. This resolves the type error and is the current best practice. Here’s an example of the new pattern:
export const authComponent = createClient<DataModel>(components.betterAuth, {
authFunctions,
triggers: {
user: {
onCreate: async (ctx, authUser) => {
await ctx.db.insert("users", {
email: authUser.email,
authId: authUser._id, // This is now available and correctly typed
});
},
},
},
});
If you are still using the old onCreateUser hook, you will not have access to _id and will encounter this type error. Migrating to the new triggers system is the recommended fix, as described in the migration guide and triggers documentation.
If you have already migrated and are still seeing this error, double-check that you are using the new onCreate trigger and not the deprecated onCreateUser hook, and that your dependencies are up to date. If the issue persists, it may be a type generation or version mismatch issue, in which case regenerating your schema and ensuring all packages are on the latest versions is recommended.
Summary:
- The type error is expected with the old
onCreateUserhook. - Switch to the new
onCreatetrigger, which provides the_idfield. - Make sure your dependencies and generated types are up to date.