intermitent failure Clerk: `const identity = await ctx.auth.getUserIdentity();`
Problem: the app works when page loads but if I reload it, the identity is null.
In development I have two apps that share the same convex dev in the same monorepo. I run them one a a time in localhost:3000, so when i use one app i don't run the other one.
This is the function that is throwing when
getUserIdentity
. It works fine on the first call, but fails after that.
Dependency:
"convex": "^1.11.0",
The auth is managed with Clerk. I set a JWT template for each app, with the same applicationID: "convex"
The other app works fine. it was the first one that i set up. The failure happens on the second app that I added.
The apps are in different url domains.
I wonder if it is a dirty state in the auth system.
Any idea how can I debug this?59 Replies
using Next.js app router
layout.js
I have also been facing this issue and have been using a workaround (probably not the best one) and would like someone to comment on this if they have a nice solution π
I think I encounter the same error
Somehow if I delete all cookies and the localstorage and try to signin again everything works again for 1 time
this is especially painful if you do something like this: signup -> singout -> singup with new account
I actually think this is the root problem of this: https://discord.com/channels/1019350475847499849/1224835051511091391
sounds related
I wonder if the applicationID has to be unique
in auth.config.js
What do you mean excactly?
I have this
so probably in the second applicationID it should be different so they are unique
but if i change the value it won't work at all
You also have to change the name in the Clerk Dashboard
Can you confirm that the minimal reproduction I made has this error you describe?
Just to make sure that I understand everything correctly
I can change the domain by changing the env variables in the dashboard. But if I change the applicationID in auth.config.js and in the clerk dashboard JWT template, then i get errors about it and login won't work
Interesting. I meant the JWT Template and applicationID so interesting that it does not work
I'm using the Clerk SignIn components. Not sure how to reproduce. I'm not creating users from the app
Ok, shoud have nothing todo with the way we log into Clerk anyways
maybe it is a Clerk error
another different thing in the app that is failing is that instead of a
users
table i'm using bz_users
but i don't think that has anything to do with identitySure, in but in my reproduction app that is not the case so this is not the problem here.
Possible, but I don't think so
@FleetAdmiralJakob π π π are you using app router with RSC pages?
Iβm not sure what could be causing this.
To change the applicationId, change the aud field in the Clerk JWT token template. Thatβs where the value βcoomes fromβ.
The other things i would try:
1. Maybe the Clerk config has an issue. Create a new one.
2. Run the apps on different ports.
Yes
But is this limited to app router?
not sure, i'll try making all pages "use client"
seems like if the auth cookie is lost
Hello, is this issue supposed to be pinned in Support channel instead of Convex Search? @Michal Srb
do you have u block origin or any other adblocker.
I never tried it out without an adblocker so maybe that's the problem.
i used in Chrome and Safari. The thing is that it works fine with the other app that shares de DB. And i copied the setup, so it is very strange. I even tried running app2 in localhost:3001 instead of localhost:3000
does it happens to you with one app using the db or multiple apps sharing db?
one app using db.
my minimal repro: https://github.com/FleetAdmiralJakob/minimal-reproduction-convex-clerk
crazy. do you have other apps that work fine with clerk+convex?
i have a bunch working well.. it is just this one that is failing
no, i have a real app having the same problem
which is your workaround? you don't validate identity on requests?
i also use pnpm
okay, maybe we have to try with npm and yarn
also does it work with the pages router?
but my other projects work fine with pnpm
I agree weird. But the other projects work fine in general
i only use app router on these ones..
okay, but maybe it helps us identify the problem
I can also write a new minimal repro for the pages router
i'm rolling back to clerk 4.29.9
that didnt help
I noticed in the network tab that when it loads a route that works it shows
_rsc
in the payload.Can you share the useQuery callsite? Do you have the component inside
Authenticated
? Have you checked the auth debugging guide?I have checked the auth debugging site. Her is what I found:
The JWT Token that is passed from the client is the correct one and works.
Despite that on the server side ctx.auth.getUserIdentity (or something like that) returns null
The debugging site says that something is misconfigure but it works for one time and and after that not anymore so I think it has to be a bug in Convex at this point
Michal. Can you validate that my reproduction has this error and that my reproduction is correctly configured?
I have the same behavior. I also noticed that in mutations it works well
yes i checked the auth debugging guide and saw the token logging once, and after that it logs null
I use mutations in my reproduction and app (and have the error) so it is not limited to queries and actions
I also noticed that the other app that i thought it was fine it also fails with identity on queries
ok, I just realized that on my other apps i was only using
const identity = await auth.getUserIdentity();
on mutations... so i had a false sense of success.The other question is: this seems to be a general issue with convex + clerk, but why aren't there much others having this issue?
can you show us your workaround?
To echo what Michal said earlier -- a really common cause of
getUserIdentity
being null is calling the function without gating on the Convex isAuthenticated
or rendering within the Authenticated
component. It's not enough to check using the clerk hooks (between steps 4 and 7 in https://docs.convex.dev/auth/clerk#under-the-hood is where clerk auth is set but hasn't been propagated to convex yet)
Looking at the callsites (the useQuery
and useMutation
calls) in your client code will probably be the most helpful in terms of debugging (and where we're checking
Concretely, I took a look at https://github.com/FleetAdmiralJakob/minimal-reproduction-convex-clerk/blob/bc2eab8e0f117babe299bae3cf7210f6661bdb3d/src/app/page.tsx#L33C10-L33C23 and it looks like we're calling the mutation without checking that isAuthenticated
is true? Instead of calling the mutation immediately, could you store state that a sign up was created and have a separate useEffect
that calls the mutation if there was a sign up and isAuthenticated
is set?GitHub
minimal-reproduction-convex-clerk/src/app/page.tsx at bc2eab8e0f117...
Contribute to FleetAdmiralJakob/minimal-reproduction-convex-clerk development by creating an account on GitHub.
Convex Clerk | Convex Developer Hub
Clerk is an authentication platform providing login via
should we wrap with <Authenticated> every component using useQuery and useMutation?
Every component where the query / mutation expects
getUserIdentity
to be populated. Other options are to conditionally call your functions (e.g. useQuery(api.my.query, isAuthenticated ? args : "skip")
) or handling getUserIdentity
being null in the functions (returning a placeholder value until auth has propagated through).
I'm not an expert on auth with Convex, and the approach you take depends on the kind of app you're building. For the personal projects I've built, I've usually just wrapped the root of my app (or a few key pages) with Authenticated
and had all my functions assume getUserIdentity
would be setooh, I didn't know that but makes a lot of sense. I didn't see that mentioned in the convexclerk guides.
Yeah I agree we can better document this (I believe we already have some stuff in the works here)
yeah it's an important point for safety. i do like better the approach from clerk that assumes everything must be authenticated and you have to manually declare public routes. This is a recommended best practice in app security. So it would be great at the auth.config.js to toggle if you want full auth expectation and whitelist individually the functions that dont need auth
btw, if you change the template name from "convex" you can't currently use
ConvexProviderWithClerk
since it hard-codes the "convex" template in useUseAuthFromClerk
@Michal Srb
@Gorka Cesium is this all set now? Was the main difference the fact that it was Next.js and a combo of authentication passes w/ intermediate state where convex wasn't authenticated yet, maybe b/c of SSR, solved by wrapping more things in <Authenticated>
?interesting, I will try out using useEffect and isAuthenticated
I just tried it but still gets identity null
finally, I found out that
isAuthenticated
does work β
, but <Authenticated>
doesnt help with the issue. So i am only going to use isAuthenticated like @sshader suggestedI wonder if the <Authenticated> is in a server component & if that's related. Sorry it's been so hard to debug. What changes to https://docs.convex.dev/auth/debug would be helpful?
Debugging Authentication | Convex Developer Hub
You have followed one of our authentication guides but something is not working.
I was trying to use Authenticated in a component with
'use client';
. It does hide things if the user is unauth, but it doesn't help with the ctx.auth.getUserIdentity()
so seems that isAuthenticated
is more in sync with convex than Authenticated
in my opinion the user shouldn't have to skip useQuery depending on isAuthenticated. In that case i might as well use the useUser hook and pass the user data as an arg to queryyeah we need to make this cleaner. One thing about using useUser is that you can't necessarily trust user data sent as arguments. A client could send up user data from a different user.
yeah thats the thing
@Gorka Cesium Authenticated just calls useConvexAuth under the hood, so it would be very surprising if it behaved differently. If you can get a repro of that issue that would be valuable.
There were some really good points made in this conversation and helped me decide the next steps. Thank you all!
interesting that in my setup i don't need to use isAuthenticated or Authenticated for mutations.
I have the same problemβ¦! will be resolving today based on the comments so far! Thank you all π
interesting that in my setup i don't need to use isAuthenticated or Authenticated for mutations.Mutations usually happen based on some user action, and by that time the auth has been setup. The Authenticated component really just makes the client "wait" before subscribing to queries in its children (by not rendering its children).
Components with queries and mutations wrapped with
<Authenticated/>
and a custom skeleton wrapped in <AuthLoading/>
has been working great for me so far!@Gorka Cesium @Nishil Faldu @Dan.Griff I'm interested whether you read through the Clerk docs first, or looked at the "example" repo linked from the top of the docs, or some other template? Trying to figure out how to guide folks better to the correct setup.
i went through the clerk guide and then the docs and then example repo. I never saw that it was a requirement to use isAuthenticated. I thought that ClerkProvider would take care of it. I look forward to the Convex Auth solution
for me https://docs.convex.dev/auth/clerk#under-the-hood this link on convex docs was very helpful for my understanding (of how things work) and I didn't actually know that
<Authenticated/>
and other Auth
components exist lol - so it was great knowing about those! After that it made sense that the auth takes some time to load and I must use some loading indicator before I render the component with queries - hence the solutionConvex Clerk | Convex Developer Hub
Clerk is an authentication platform providing login via