Have you had a chance to explore `Better Auth`
Have you had a chance to explore
better-auth
yet?
I'm using this adapter @better-auth-kit/convex
and its instructions (https://www.better-auth-kit.com/docs/adapters/convex, https://github.com/ping-maxwell/better-auth-kit/tree/main/packages/adapters/convex)
and these instructions too https://www.better-auth.com/docs/installation
and then set up Github OAuth, as the simplest way to get started: https://www.better-auth.com/docs/basic-usage
But running into various issues.
Convex Auth was seamless and easy. But I've concluded that better-auth is what I want to bet on long term b/c it seems to be an emerging standard in the JS ecosystem imo, is fully featured, not tied to any specific provider, etc.
Blocked on integrating convex further now.107 Replies
1. First issue was getting it to build. I created an issue for @Ping 's repo for that: https://github.com/ping-maxwell/better-auth-kit/issues/5 Editing the built files in node_modules just to keep going with this, so they used
.js
extensions on imports, allowed the project to build without errors.
2. Now, getting a runtime error when trying to use better auth's authClient to sign in with Github OAuth, and it's like my Convex URL cannot be found anymore, but I've had Convex working on this project prior to better auth
Thanks for this - I'm looking into another integration approach now
🙏 awesome
Update: I got past the first build error:
1. Ping pushed an update to address it, so use this version or newer
"@better-auth-kit/convex": "^1.1.4",
2. And I also needed to update my convex/tsconfig.json
from "moduleResolution": "Bundler",
to "moduleResolution": "bundler",
. I don't recall setting this, so a default might need to be updated in Convex's code generation b/c TypeScript indicates that only lowercase is valid.
Progress! Now the runtime error listed as #2 in my previous post still occurs trying to use the Github OAuth method to sign in. So, that's the next hurdle.
Just noticed I have no better auth tables in Convex either. I might be messing this up, but I assume the tables are created after running npx convex dev --once
as long as convex/betterAuth.ts
exists.Yes that's right.
Looking forward for this :convexspin:
🙌🙌
Hi,
Did you use the JWT plugin of better-auth ?
Did Convex recognize it ?
Sorry for pinging you, but any chance we get a native adapter any time soon? I really would like to use betterauth together with convex in my tanstack start project and looking forward to it
No problem - too early to say for sure, but will update here.
For anyone following this, would it be useful to have pretty standard auth working with Convex and BetterAuth or are you hoping to use specific plugins?
Just a heads up, has been some discussion with @ballingt and @Wayne about integrating Better Auth with Convex. Not sure if you knew that already, but just wanted to throw that out there.
Was literally just about to @ you lol
yeah I'm aware, been thinking about whether our work would end up converging or something, but we should talk
When I saw you wrote a tokenizer for this my head exploded lol, mad respect
haha, thanks
Yeah, it would be really great if we can have some sort of native integration.
Might be worth if I get Bekacru in here and we can chat about this
Convex just doesn't handle arbitrary queries, so it's going to be a different integration than the others. The approach I'm looking at is basically a BetterAuth Convex Component that wraps BetterAuth and provides specific functionality (and more support for specific plugins can be added ongoing).
specific functionality as in predefined functions for specific DB interactions?
Exactly. There can be a lot of sharing I think, but yeah a good number of functions and predefined tables/indexes.
Hmm. That might be challenging. Better Auth Adapter model allows our internal code & any plugins to call the adapter to do mutations or queries any way they like, could be a little unpredictable depending on the situation..

I'm wondering if that varies depending on the functionality supported. Like BetterAuth does a lot - but if the initial support model is just auth, and we pin the Convex component to a specific version, that narrows how many queries can occur
Yeah I think this is our most recent conclusion from @ballingt , but there might be more to discuss

I have basic sign / sign out with oidc (required for Convex custom auth integration) working right now
cc @bekacru
I see
I fully agree w/ Tom's conclusion and your approach - if dynamic queries can be made to work in Convex, that's ideal. I just don't know if it's fully doable, just based on the caveats in the integration docs alone. Convex is really built for schema, indexes, and queries to be predefined in code, and everything is optimized for that. That said, having built the integration so far you may have a different outlook on the challenges?
For feasibility on predefined queries, having a BetterAuth Convex component that exposes certain configs to the user and pins a specific BetterAuth version is definitely required. Not ideal, but the integration can feel very Convex native. And the adapters in the better auth source do provide a nice set of indicators for what queries to expect for a given provider or plugin.
The ideal goal is to have everything done in 1 request, and make it support transactions.
Since right now, every req goes through a Convex action, then to the mutation/query call, this alone could be 1, 2 or maybe even 3 requests, and all of it is not transactionable as far as I'm aware
I think that if we want Better Auth to work with Convex "seamlessly", it may have to use external/special code specific for Better Auth to work, using the current Convex DB functionality will probably only get us as far as what I've done. 🤔
Like a special Better-auth integrated Convex action sort of thing
Like platform level support you mean
And yeah having everything be a transaction would be awesome
Is your integration running better auth in an action or a mutation?
Yeah 😅
As far as I'm aware, Convex DB uses sqlite? So it would mean that we'd need a custom adapter that can do direct queries to the DB internally? Not too sure..
My platform knowledge is zilch, but I'd be surprised if that were possible without breaking the whole model given Convex databases are entirely transaction based
But again zilch is the important word there lol
Kind of both.
Since the mutations & queries are using internalMutation/internalQuery, so everything runs through a Convex action, parsed and whatever else, then goes to their respective internalMutation/internalQuery
Gotcha, and better auth itself is being run in the http action and calling queries/mutations from there
better auth would have to run in any of the current supported integrations, it doesn't work in http actions
If it were possible to pass an object representing the request instead of the actual request, it might be possible to run better auth in a mutation, although fetch is only supported in actions
So for example, BA would run in Nextjs, and Convex is just there for DB or whatever else the user is using it for.
Ahh hmm
I'm actually running it in an http action
But I'm testing with Vite, not a framework like Next.
Right now? You got it working?
Yeah it works in http actions fine
The OIDC plugin is 🔥
I haven't actually tested it, but I kind of made assumptions that things would break unexpectedly, as that's my experience in some other things in the Convex enviroment
The one thing that didn't work was jwks creation, as the convex runtime subtle crypto implementation doesn't have generateKeyPairs, so I just made a jwks record and stuck it in the jwks table
Otherwise it was good
Just what I was about to say..... 💀
the one thing I tested in HTTP action was using
jose
to parse JWT
and it didn't work.
Okay.. so everything else works then...Parsing it can actually do fine
oohh
the alg, had to use rs256
ed25519 support has a bug in convex runtime, you may have run into that
I really wished I had asked you guys about this now, I just made the assumption that "things just don't work"
🤦♂️
to be fair, there wasn't a clear answer on the stuff you ran into, I spent half of yesterday figuring these parts out
Yeah... literally exactly that.. How unlucky xD
Oh I see
the more you learn I guess
Anyway, back to HTTP action working with BA, that's really 🔥
I have some good progress on the Convex first approach, going to share something that works soon
Super awesome to hear. I might have to add this to my docs
Also making it a Convex Component will be a nice touch, separates auth tables from the user's app tables, and keeps the integration surface clear
What is a Convex Component?
Convex's integrations layer
Basically the components architecture means a Convex app is actually a component (the "root" component), and you can install other sort of sub-apps with their own sets of tables, functions, etc, and they expose functionality to your app (or other components) through a client api that the component itself defines.
okay... interesting.
Could you give me an example of how I can merge this with the Better auth adapter idea?
It doesn't change anything on the dynamic query support front, the challenges you've outlined would still be there
The approach I'm thinking of is a BetterAuth Convex Component would support a config similar to better auth, but limited to the things the component actually supports. But it'll feel super native and can be even simpler to set up than a standard db integration with BA
Have to say, BetterAuth is a very nice piece of software. API's are so well thought out, and it has so many things that just work
how dumb is it to just use better auth jwt and a pg db or something like that
i got it to work but i dont like having two dbs.
Not dumb, just preference.
Thank you @erquhart for working at this ! It would be awesome to have a Convex Component for that !
Update on my end: I have Better Auth's Email OTP plugin working, to create a user, create a session, and delete a session on logout. (Better Auth's OAuth still encounters runtime errors, so I'll just hide that option on my login page for now.)
Remaining to sort out: 1.) protecting private routes--i.e. to redirect to
/login
if unauthenticated, 2.) writing a helper to require authentication for certain Convex mutations & queries, 3.) making user object available to all routes.
Do y'all have more clarity now on if a deeper integration between Convex & Better Auth is required? Asking b/c if so, that'd help me know to just pause my attempts for now.I definitely wouldn’t discourage use of the BetterKit integration. Some of the Convex integration issues you’re hitting might be already solved in the component, though, so I may be able to publish a very (very) early version if you want to try it out. Would need to know which BetterAuth features you’re looking to use and what framework you’re running (next, tanstack, etc) if so.
- TanStack Start + BetterAuth + Convex.
- Goal is Email OTP & Github OAuth. But for now, just Email OTP, b/c OAuth has runtime errors (already reported on the better-auth-kit repo). I have Email OTP working to sign in/out, just not the 3 aspects listed in my previous message.
- An example of Convex+BetterAuth with any JS framework, that's full enough to cover protecting private routes and protecting convex mutations & queries, would be immensely helpful as a reference
- Non-goal for MVP, but security critical for production: getting BetterAuth's rateLimiter working with its database adapter. BetterAuth uses memory as the default store for its rate limiter, which isn't effective for serverless hosts. (I updated BetterAuth's config to use database storage, but this table is not created automatically which I assume it should be, on Convex, if in use. I haven't tried to create the table manually yet b/c I'm focused on the 3 items in my previous message. But Email OTP will need rate limiting to be secure in production, so I'll spend some time on this later.)
Would this limit ability to alter the users table, like to add an active
planId
for a SaaS? Otherwise sounds cool
I can also create a repo from my current TanstackStart+Convex+BetterAuth project, that has working Email OTP and redact my private stuff, if you'd like to hack on it to create an example. Might help us both outThe short answer is no, just need to determine the best API for this part. Would like the users table to be in your app and not in the component's space, but it's tricky.
I have things working with next, I need to make a tanstack example anyway so I'll get one together and update.
any chance to get a early access before the weekend?
Sharing today
Hey folks, it's late, but it's technically still "today" here on the east coast 😅
Convex + Better Auth - Comprehensive authentication for Convex Apps
Type-safe, secure authentication for Convex applications. Supports email/password, social auth, magic links, and 2FA with a beautiful developer experience.
This is very early alpha! Please test it out, feedback appreciated.
Thank you!
Gonna have a look later
Thank you so much !!!!!
I will test it today !
Okay, update time: I’m not in a position to look into this until Monday, but any auth strategy besides password will fail because of cross domain cookie policies in every browser that isn’t based on Chrome (that I’ve tested at least). More to come, but for actual usage today, use email and password.
good work and good start
Is this also the case why google auth doesnt work too? Google tells me that I’m getting redirected to a non authenticated url
@erquhart could you add a query to use the email index. i dont want to have that much duplicate data. also if there's a way to query data of a component without it exporting a function please let me know, i didnt see anything about that. thanks 🙏
You can’t directly query component tables - this ensures components aren’t accidentally breaking user apps in successive releases by allowing the component to define its own api. Can definitely add looking up user by email.
i didnt thinks so, also thanks for that.
i appreciate it
i guess you plan to finish some of these features later but id like list-sessions support too. seems easy enough maybe i can contribute when i get time
Yep, makes sense to add. Can you share a little of your use case for that? We should have it either way, but want to understand how it’s being used.
Just to have a list view to display them and delete them
Basically log out of any devices
Maybe the user will see some unrecognized location
Does anyone know, how to use it with tanstack start in an api route?
this is given by the betterAuth docs for tanstack, but using the convex component the auth.handler function isn't found
You don't need to do that because the API routes are on convex site @gegi
const session = await auth.api.getSession({
headers,
query: {
disableCookieCache: true,
},
});
Maybe ?
I'm trying something like this now:
and I want to make it avaiable to my context
Sadly not getting it to work as expected with the email provider in my tanstack start project. Looking forward for a tanstack start demo page :(
What are your plans with plugins that need a migration step like https://www.better-auth.com/docs/plugins/organization ?
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
RE cookies: I'm assuming a Convex custom domain would solve that. But this makes me curious...how does Convex Auth handle cookies, given a user's website domain differs from their
*.convex.cloud
backend? Does that use JWT or something instead?
(I personally like Better Auth being cookie-based especially with their cookie caching feature. Just curious.)Current user sessions, gotcha
Just need to add support for it, figured folks would be interested in this one. I expect the first class better auth plugins should all end up being supported, so it's just a prioritization thing. Will look at this one.
Server auth will be tricky, again it's down to cookies and cross domain requests. A typical Better Auth implementation is on the same domain as the app using a full stack framework, but that isn't the case with Convex. Today I'm looking into either proxying or making bearer tokens work.
That said, I'm also curious on the choice to use server functions vs just using Convex functions. Is there an advantage for you or just ergonomic preference?
(server auth needs to be supported either way, this is just my own personal curiosity)
I would like to have the information on beforeLoad in tanstack start
but it’s more a ergonomic preference
I'm curious as to what the ETA would be on this roughly
The org plugin has a lot of functionality, would take some doing - would definitely recommend Clerk if you need orgs right now, as basic functionality is still being nailed down for this integration.
Sounds good, will be following this project
Heyo @erquhart did you find the timeto make a tanstack start example working? 😁
Got this up an running. Confirmed that Google auth is working in Safari
Did you do anything to get that going beyond just setting up?
Works the same as next for now, just client side. Follow steps for Convex with TanStack, but use the convex better auth provider from the doc instead of standard convex provider.
I've been trying to get this up and running in Next.js, but am getting stuck with email OTP. The isAuthenticated state isn't getting saved to local storage (or to Convex?), so when I succesfully receive an email OTP code and enter it to verify, I'm not being redirected to the dashboard page because it still thinks isAuthenticated is "false". Any idea where I might be going wrong here?
isAuthenticated won't be persisted anywhere, it's a reflection of the current session auth state. Are other methods working and just not this one?
@erquhart Heard. It does seem to be only isAuthenticated that isn't working. This is what my Network tab in chrome devtools looks like through the email OTP sign-in flow

hmm I've no clue what that
/is-authenticated
call is, I don't believe there's any such endpoint in better auth, and def not in the convex integration
I'm sure the answer is "no" but can you just grep your code quick to make sure it isn't in there somewhereYou're right, it's not in there anywhere, just the
const { isAuthenticated, isLoading} = useConvexAuth();
that is straight from your example repo
Got it working finally! I've been trying to rebuild your example repo line by line to teach myself what's going on each step of the way (since I've built apps with convex and better-auth separately and really wanted to understand how they were being stitched together), and there was a weird function that Cursor threw into my app at some point that was messing things up.
Thank for putting this together and helping everyone out in this channel and asking a lot of good questions over on the better-auth discord 🙂
My next follow-up question is, social logins easily pull name and profile image data from the provider during sign-in, but what's the best approach for this w/ email OTP sign-in?Have the user provide their name and upload a profile image. You could use something like Gravatar for the profile image, too.
How would I build a mutation to patch changes directly to the better-auth component table? Or is the better method to add a name and image field to the users table created for our actual app's database and read from those instead of the table from better-auth?
Nope, just followed the directions listed. I did have to reference the example next app in the repository though.
Do you think there's any way to get Server Side Auth Working? https://docs.convex.dev/client/react/nextjs/server-rendering#server-side-authentication
It's usually
await betterAuth.api.getSession()
but betterAuth doesn't have access to .api.getSession()
We do have access to betterAuth.getAuthUser()
but that required ctx
to be passed which I believe requires a convex function (client).Next.js Server Rendering | Convex Developer Hub
Next.js automatically renders both Client and Server Components on the server
Tried the following approach for server side auth and no luck.
Recommendation is to create your own users table that hold only extra data. More on working with users here: https://convex-better-auth.netlify.app/
just realized section links aren't in the url - look for "Working with users" in the left sidebar
In the docs here, the BetterAuthOptions type is declared but not used.

You’ll get type errors without it if you use any of the hooks in that setting options object, function references cause circular inference and I haven’t found a better way to address it yet.
But yeah with no hooks you can omit it.
Any guidance on how to set up the provider for Tanstack? It's a bit more complicated than the Next or Vite examples. Stuck on error of
Type 'QueryClient' is missing the following properties from type 'IConvexReactClient': setAuth, clearAuth
Ah yeah it is a bit different. I need to dig into this, but it will likely look similar to the instructions for using Clerk with Convex and Tanstack: https://docs.convex.dev/client/react/tanstack-start/tanstack-start-with-clerk
There's server side stuff in that guide too, which doesn't apply yet for the better auth integration. I'll add a proper tanstack example once the cookies issue is resolved (we basically need to just use jwts instead of cookies with better auth), working on that now.
Adding anonymous login would be nice too :ezpepe:
Yeah need to add support for that plugin, on the list
better auth provides a plugin to handle cookies
https://www.better-auth.com/docs/integrations/tanstack
TanStack Start Integration | Better Auth
Integrate Better Auth with TanStack Start.
Maybe you can use that for your implementation
unlucky 😔
for now
excited 😁
@erquhart how should i authorize on http actions? do i need to just add a method to query the better-auth.session_token
nevermind actually i got an idea
You generally want to treat http actions like webhooks, usually a shared secret is enough