Roast of the convex client and authentication.
What I want to achieve without crying out loud:
1. Call an endpoint that checks the cookie and returns the session
2. Use that session cookie when calling fetchAccessToken
3. Authenticate into convex server using the JWT so that i can use ctx.auth.
Simple right? It's all that really matters when building auth and connecting to convex server.
In the current state STEP 3 is terror. Who's the culprit?
Convex Client - a nice block of concrete with cracks.
First of all... It doesn't clear the scheduled fetchAccessToken calls when transition to unauthenticated state, but you probably didn't notice that, because who's testing 10s access tokens or waits after signing out.
Ok I will opt-out from refreshing and add it myself. Yeah you bet it's baked in.
You have no access to the internal state and you cannot observe and react to events like authentication.sent authentication.success and so on.
I mean you have
onChange
callback right?
Yes and no. You are signing out clearing the auth, but you won't receive the callback... It just sends the message over websocket and doesn't notify you back when it's done, if it's done.
In the current state you cannot treat client as a source of truth as you should be!
This is the root cause of component unmounting hacks and layers of setState, useEffect everywhere. Great example of that is FirstEffect and LastEffect in one of the convex providers. You can follow the provider guide and just use tanstack suspense query in the authenticated part, sign out and you will find another one despite all of the efforts.
The more you dig in the more problems you find.
Integrating custom provider and extending auth should be simple and reliable as the rest of the convex environment but it is a nightmare.
I do really love the rest of the product but it is super frustrating when you are unable to work around the problems because of the software limits.
Are there any improvement plans?12 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!
@machi now that you've pointed out these issues, yes (I didn't know about these)
1. let's make clearAuth should cancel scheduled token refreshing, 100%
2. a different api for auth that lets you refresh the auth instead of doing it automatically; that's possibly but ugly today, you can make the scheduled one a no-op and call setAuth(() => yourTokenYouRefreshedSomeOtherWay) - curious what api you want here
3. sounds like clearing auth doesn't call the callback, yuck, that's wrong; wonder what onAuthChange was added for then, we'll fix. Re confirm from the server, yeah this is a limitation, I'm not quite following what you need this part for but it should be there, auth state needs to share more. Some related work described in https://github.com/get-convex/convex-react-query/issues/19, you should be able to e.g. set auth up front and prevent running any queries until it's been confirmed, although whether that coordination should be internal or external to the client I don't know
re 'sign out and you will find another one' bit are you describing another issue or this whole mess?
re firstEffect/LastEffect, this is complicated and sticking the state machine in React makes this read worse, effect order in components is specced but sure not easy to read, but seems like what's necessary while this logic lives in React
A big rework is not planned soon, but for specific use cases that are important (e.g. SSR, suspense) we'll do whatever it takes to make these work. One planned change is the guarantee that auth is received before queries are evaluated; that's mostly an ordering thing on the client
I found out that even with all those preventions to unmount queries somehow I receive the query call after the wrongly scheduled fetchTokenAccess is called.
This one is very wierd and I don’t know why it happens
I checked and I do not rerender
just filed an issue for (3) https://github.com/get-convex/convex-js/issues/63
The component that holds this suspense query
We need an example with TanStack + Auth, it doesn't exist yet but it's something we should (make work first, and then) be testing
there's an example with Clerk but we're not doing authed SSR with it
It’s all client side
TanStack stuff keeps getting delayed waiting for stability but it's time
Ok There is a helper for better use query in helpers any chance that we get same for mutations and actions
I think that would reduce the need of tanstack in general
Regarding server confirmation it is just a general concept of being able to hook into them as a developer. if you have granular events access I can code around them create my own state and stop bothering you haha
Regarding that. What if I don't want to use ConvexWithAuthProvider?
I know how the convex auth works and I want to unmount views myself without hacking around with useEffects.
Example:
1. Press the sign out button and call clear auth
2. Now I would like to receive notification
send_authenticate "none"
before sending message in order to set the state to signout-pending
3. I unmount authenticated view when state === signout_pending
and render placeholder loading view until I receive some event with authenticated: false
.
4. Now I can remove the session and perform my session signout implementation.
5. I have a consistent convex connection and I have consistent session state.
In this flow I would not need any of that useEffect stuff. I simply maintain the correct unmounting order myself
I think lower level of onChange
would be great because most of these kind of problem would be possible to solve and you could work them around yourself
Here are some LOGS from convex and the last one is basically an event that could be exposed.
This could also potentially allow me to work around the tanstack problems where needed based on the convex state.
I don't think that re-exposing the ws messages makes sense but important auth state before/after transitions
Regarding the tanstack query here is an example reproduction of previously mentioned bug.
⏰ Now when you sign out isAuthenticated is false and this query is not being properly unmounted and you receive the query call on the server. There is no mutation to the user. SUPER WIERD.This on is interesting, we stay subscribed to queries for a while when using the TanStack Query integration. When we setAuth or clearAuth that causes all of these to refresh. That's desirable when it's carrying new information from the JWT, but not when logging out.
One planned change is the guarantee that auth is received before queries are evaluated; that's mostly an ordering thing on the clientI am very happy to hear that this is planned. At the moment, all my Convex queries have an initial auth check and return
null
if it's not set (rather than throwing). This is because when I throw it seems the Convex query subscription isn't automatically retried when the auth becomes available.
This results in needing to handle null
for all queries on the frontend at the moment.The not retrying behavior sounds like a bug, could this be because the component unmounts if an error is thrown? On receiving auth every query that checks auth should rerun
a repro would be helpful here if these aren't rerunning
but regardless agree that needing to write queries so that they work without auth is frustrating