shea
shea4mo ago

IdTokenExpired on using convexAuthNextjsToken in production

Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-08-27 01:49:03 UTC (cur
63 Replies
sshader
sshader4mo ago
This sounds unexpected since the auth library should be handling refreshing the tokens for you. I'll try and reproduce to see if there's a bug on our side, but could you share any more details on your set up? Also clearing cookies will likely temporarily solve this by forcing you to go through the full auth flow again
shea
sheaOP4mo ago
@sshader ok so, I setup google oauth on convex auth, once you login with google, then come back to site later it shows this error always. My 3 projects are broken. In development. it shows error too but it upon refresh it get fixed but in production it stays broken
sshader
sshader4mo ago
Do you have any logs or error messages you can share (client side logs, convex dashboard logs)? What version of Convex + Convex Auth are you using?
shea
sheaOP4mo ago
"convex": "^1.14.0", Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-08-15 15:13:26 UTC (current time is 2024-09-06 19:50:37.295413176 UTC)"} at m.queryInner (/var/task/.next/server/chunks/442.js:62:74422) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async m.query (/var/task/.next/server/chunks/442.js:62:73826) at async P (/var/task/.next/server/chunks/258.js:1:14870) { digest: '4279888865' } this is in vercel logs convex prod logs: Sep 07, 01:20:02 M auth:store error 'Invalid refresh token'
shea
sheaOP4mo ago
No description
sshader
sshader4mo ago
I'd recommend upgrading to latest Convex (1.15.0) or at least 1.14.4 + clearing cookies
shea
sheaOP4mo ago
@sshader same issue how come in dev, full reload fixes the issue
shea
sheaOP4mo ago
No description
shea
sheaOP4mo ago
aah did you guys abandon this project lmao
sshader
sshader4mo ago
Can you describe more of what you're seeing and some potential steps to reproduce? That looks like a completely different error from before
erquhart
erquhart4mo ago
I just ran into this too, the original error from OP that is I'm only running dev, haven't tried in production. The second error described didn't happen for me. But it seems convexAuthNextjsToken() is returning a stale token, and presumably getAuthUserId() is then throwing. But on refresh everything works.
sshader
sshader4mo ago
Cool -- sounds like this is an error thrown on the Next server during SSR then?
erquhart
erquhart4mo ago
Yeah, it's a server component
allen
allen4mo ago
I'm also occasionally coming across this in dev and production. It seems to be when the token is somewhat stale (always happens when returning to work the following day). The first attempt at accessing the token fails, but upon refreshing the page, it refreshes the token and continues as expected. This is in SSR using isAuthenticatedNextjs(). It seems that method is throwing the error, not when subsequently using the token it returns, causing the page render in Next to return a 500. This is using convex@^1.15.0 and @convex-dev/auth@^0.0.61 I'm curious if @erquhart and @shea also have isAuthenticatedNextjs() in the same file, as I suspect its that method, not convexAuthNextjsToken(). I'm also using convexAuthNextjsToken(), but my stacktrace leads me to isAuthenticatedNextjs(), and this seems to make more sense. The token fetching works fine, but authenticated status is unable to be successfully determined from it as it requires refreshing.
agun40
agun404mo ago
const { signIn } = useAuthActions(); const [flow, setFlow] = useState<"signIn" | "signUp">("signIn"); const { toast } = useToast(); const [submitting, setSubmitting] = useState(false); const storeAdmin = useMutation(api.admin.storeUser); const router = useRouter(); const renderForm = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); setSubmitting(true); const formData = new FormData(event.currentTarget); const email = formData.get("email") as string; const password = formData.get("password") as string; console.log("Form Data:", { email, password }); try { if (flow === "signUp") { // Sign in the user first to ensure authentication await signIn("password", formData); // Now call the storeAdmin mutation await storeAdmin({ user: { email, name: "Admin", password, role: "admin" } }); } else { await signIn("password", formData); } router.push('/admin/dashboard'); i am getting undefined and null import { query } from "./_generated/server"; import { v } from "convex/values"; import { User } from "./type/userType"; export const getUser = query({ args: { email: v.string(), }, handler: async ({ db }, { email }) => { const user = await db.query("users").filter(q => q.eq("email", email)).first(); return user || null; }, });
allen
allen4mo ago
@agun40 your issue appears to be client side. I have never had an issue there, only server side.
agun40
agun404mo ago
how can i solve the issues This is my schema // convex/schema.ts import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; import { authTables } from "@convex-dev/auth/server"; export default defineSchema({ ...authTables, users: defineTable({ name: v.optional(v.string()), image: v.optional(v.string()), email: v.optional(v.string()), emailVerificationTime: v.optional(v.number()), phone: v.optional(v.string()), phoneVerificationTime: v.optional(v.number()), isAnonymous: v.optional(v.boolean()), // other "users" fields... role: v.optional(v.string()), }).index("email", ["email"]), admin: defineTable({ email: v.string(), // Add the email field name: v.string(), tokenIdentifier: v.string(), }).index("by_token", ["tokenIdentifier"]), students: defineTable({ email: v.string(), role: v.string(), password: v.string(), }).index("email", ["email"]), teachers: defineTable({ email: v.string(), role: v.string(), password: v.string(), }).index("email", ["email"]), }); this is my mutation function export const signUpAdmin = mutation({ args: { email: v.string(), name: v.string(), password: v.string(), }, handler: async ({ db }, { email, name, password }) => { // Hash the password const hashedPassword = await bcrypt.hash(password, 10); // Insert the admin user into the admin table await db.insert("admin", { email, name, password: hashedPassword, tokenIdentifier: "", // Initialize with an empty string or generate a token } as { email: string; name: string; password: string; tokenIdentifier: string }); }, });
shea
sheaOP4mo ago
not to be rude but If this is not fixed in 1 week i am migrating back everything to supabase. Its been too long this obvious bug in production. Not sure if you guys even care but this is frustrating cause my 2 clients are bugging me.
allen
allen4mo ago
Are you using isAuthenticatedNextjs(). Could that be what's throwing in your case?
shea
sheaOP4mo ago
getNextjsAuthTOken() something const user = await fetchQuery( api.users.viewer, {}, { token: convexAuthNextjsToken() } ); culprit^
allen
allen4mo ago
After reviewing the code, I'm not sure how it could be throwing on either of those methods directly. My stacktrace must be incorrect. The error must be thrown when failing to refresh the token in some situations when making a query call using it. https://github.com/get-convex/convex-auth/blob/30c4f2fcc91ab4e92084bd20b8094e68b3d3487a/src/nextjs/server/index.tsx#L78-L91
GitHub
convex-auth/src/nextjs/server/index.tsx at 30c4f2fcc91ab4e92084bd20...
Library for built-in auth. Contribute to get-convex/convex-auth development by creating an account on GitHub.
allen
allen4mo ago
This appears to be the origin of the error being thrown. Unsure why refreshing isn't happening upstream in some cases. https://github.com/get-convex/convex-backend/blob/fe8f698addd4fadcfe14bbd90f25c98a243313a5/crates/authentication/src/lib.rs#L124
GitHub
convex-backend/crates/authentication/src/lib.rs at fe8f698addd4fadc...
The Convex open-source backend. Contribute to get-convex/convex-backend development by creating an account on GitHub.
allen
allen4mo ago
Whats odd is I don't see any errors logged in convex's backend. upgrading to @convex-dev/auth@^0.0.65 and will observe. Is there a way to configure the token ttl so this can be tested in a more rapid fashion?
shea
sheaOP4mo ago
no nothing upgrading seems to work, I tested it all. I will try again
agun40
agun404mo ago
hi, can you help me with mine
allen
allen4mo ago
@agun40 I see you created a separate support thread for your issue. Why don't we move the conversation there?
agun40
agun404mo ago
okay let go there sir
allen
allen4mo ago
Can confirm. Upgrade did not solve. Stepped away for an hour, refreshed my browser, and the error was thrown. Refresh again, everything is fine.
allen
allen4mo ago
I do see this in the convex logs
No description
sshader
sshader4mo ago
Cool thanks y'all for all the extra details -- I'll try and reproduce this myself. If one of you has a handy repro and wants to be extra helpful, turning on verbose logging (https://labs.convex.dev/auth/debugging#enabling-verbose-logging) and sending me browser logs + convex dashboard logs would help me investigate.
Debugging - Convex Auth
Authentication library for your Convex backend
sshader
sshader4mo ago
Is there a way to configure the token ttl so this can be tested in a more rapid fashion?
I think the configuration is here: https://labs.convex.dev/auth/api_reference/server#jwtdurationms (I've been setting this to like 1 minute myself when trying to reproduce various issues)
server - Convex Auth
Authentication library for your Convex backend
allen
allen4mo ago
Ok, I'll reduce the ttl and add verbose logging to try and help diagnose. @sshader i suspect preloadQuery / fetchQuery isn't awaiting the refresh and proceeding with a stale token. I've yet to see this on the client side with useQuery et al. the fact the problem doesnt emerge on the second attempt tells me that the refresh does resolve, and stores a new token, just not in time for the original request. It doesn't look like the jwt config is taking. auth.config.ts
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: "convex",
},
],
session: {
jwt: {
durationMs: 60000,
},
},
};
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: "convex",
},
],
session: {
jwt: {
durationMs: 60000,
},
},
};
Wait for deploy, then log out of app and back in, and here is the issued token in cookies, expiring in 1hr still.
allen
allen4mo ago
No description
shea
sheaOP4mo ago
Sep 16, 21:49:00 M auth:store error 'Invalid refresh token' I shared all this before too idk why we resending it if someone is not even actively looking into it
allen
allen4mo ago
I've triggered the error again with verbose logging enabled, but it doesn't look any more verbose.
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.372223769 UTC)"}
at async Moments (home/components/moments/index.tsx:27:27)
digest: "1358332306"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.372933967 UTC)"}
at async Activity (home/components/activity/index.tsx:17:27)
digest: "2780878193"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.394172138 UTC)"}
at async AuthProvider (./providers/auth/index.tsx:23:30)
digest: "3678790953"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.394172138 UTC)"}
at async AuthProvider (./providers/auth/index.tsx:23:30)
digest: "3678790953"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.393474478 UTC)"}
at async Followers (home/components/followers/index.tsx:23:27)
digest: "2942702038"
GET /home 500 in 453ms
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.372223769 UTC)"}
at async Moments (home/components/moments/index.tsx:27:27)
digest: "1358332306"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.372933967 UTC)"}
at async Activity (home/components/activity/index.tsx:17:27)
digest: "2780878193"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.394172138 UTC)"}
at async AuthProvider (./providers/auth/index.tsx:23:30)
digest: "3678790953"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.394172138 UTC)"}
at async AuthProvider (./providers/auth/index.tsx:23:30)
digest: "3678790953"
Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-16 16:08:29 UTC (current time is 2024-09-16 16:54:09.393474478 UTC)"}
at async Followers (home/components/followers/index.tsx:23:27)
digest: "2942702038"
GET /home 500 in 453ms
This is all from my next dev console output. I see nothing related to the error in convex logs. @sshader if you have any other ideas on how I can assist, let me know. Without being able to successfully reduce the ttl of the issued id token, it makes it difficult to bang on.
Wayne
Wayne4mo ago
Hi everyone, please remember our Guidelines and Code of Conduct, and we're a small team. If you're a Convex Pro customer, it's best to email via the Convex Dashboard for email support. All other support from the community is provided on a volunteer basis.
sshader
sshader4mo ago
Thanks allen for the help so far -- I'm trying to set up my own repro as well (btw I think you want jwt: { durationMs: 60000 } up a level instead of nested under session, and this should be in auth.ts when using Convex Auth instead of auth.config.ts) Aight -- new version of Convex Auth hopefully fixes this (0.0.67)
allen
allen4mo ago
I'll give it a spin. ttl config is working and refresh seems to be happening flawlessly! I'll keep monitoring, but seems like its fixed. Hmmm actually now I'm observing getting logged out automatically. If I login, then just let the page idle, it will flip back the the <Unauthenticated /> view after a couple minutes (this is with a durationMs of 60000) Althought I'm having trouble reproducing, so I'll keep observing...
allen
allen4mo ago
Definitely still happening. Logs in convex:
No description
sshader
sshader4mo ago
I think there might be a different bug where two things can race to use the same refresh token which is what I want to look into next
allen
allen4mo ago
that would make sense. I have multiple server components that would try to fetch simultaneously on app load
shea
sheaOP4mo ago
I think it's fixed but now it logouts often.
allen
allen4mo ago
@sshader let me know when you are ready for more testing. I reverted back to 0.0.65 due to the issue making auth state to fragile.
shea
sheaOP4mo ago
new convex auth does not fix same error Application error: a client-side exception has occurred (see the browser console for more information). Error: {"code":"IdTokenExpired","message":"Expired: ID token expired at 2024-09-17 12:04:54 UTC (current time is 2024-09-17 23:17:20.734180922 UTC)"} at C.queryInner (/var/task/.next/server/chunks/5167.js:1:30941) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async C.query (/var/task/.next/server/chunks/5167.js:1:30345) at async m (/var/task/.next/server/chunks/3818.js:1:14828) { digest: '3592468013' }
sshader
sshader4mo ago
Ok another version is out -- 0.0.68 with another attempt at this
allen
allen4mo ago
Feels good so far. I did get one logout and a console error of "Convex Auth: Unexpected missing refreshToken cookie during client refresh" early on, but it hasnt resurfaced. May have been some latent state from the earlier session.
allen
allen4mo ago
I've pushed it to prod and still see the logs peppered with "Invalid Refresh Token"
No description
allen
allen4mo ago
I don't know how its getting in this state, but once it is, its stuck there as nothing clears the cookie with the back refresh token value. So every request to convex tries to run a refresh routine and fails. My best guess is that multiple synchronous queries executing a refresh and all requesting new refresh tokens. This introduces a race condition where a stale, invalidated token can get persisted to cookie storage. This then puts everything into a bad state which there is no recovery (short of manually deleting cookies) as the bad cookie value is never cleared once identified as bad. However, this is speculative as I havent taken the time to dive into the code around this. Hopefully my uneducated musings based on observed behavior are of some help.
sshader
sshader4mo ago
Hmm not clearing cookies on this is surprising to me -- if you happen to see this again and have the network tab open (can see any of the network requests and see if they're setting / clearing any of the relevant cookies), let me know. Will also continue to try reproducing all these errors.
allen
allen4mo ago
I'm also experiencing something thats hard to describe. Essentially in Route A with its own auth guard component in place links to Route B with different instances of the same auth guard, route B throws errors about being unauthorized, even though Route A wont present a link unless they are in a logged in state. I'm happy to hop on a call and walk through this all if its helpful. Not sure that my component layout/structure is the culprit. seeing some similar behavior just naving around the same component layout. It will just suddenly boot me out and (this time) successfully clear cookies.
allen
allen4mo ago
You can see it thinks the token is invalid during a refresh, yet a bunch of queries resolve out with cache, then suddenly things start failing.
No description
lexcodeit
lexcodeit3mo ago
Thank you Allen for your help in fixing this so far. I'm still stuck with this error. Please any new solutions. The worst of it all is that I cant even logout of my web app to be able to sign in and create new tokens. This only happens on nextJS
lexcodeit
lexcodeit3mo ago
This issue here is that in my middleware This isAuthenticatedNextjs()) returns true; This isPublicPage(request)) returns false; But the refresh token is expired. So I don't know how to handle the logic from here onwards. Or how to clear the token stored so it doesn't assume I have an active session.
No description
allen
allen3mo ago
@lexcodeit I'm still working through this with Convex support outside of this thread. Not experiencing some of your issues though. What version of convex auth are you using? isAuthenticatedNextjs is rather dumb, just evaluating if there is an auth token cookie present, so don't extend it too much trust. However, if everything is working properly, that token should be cleared if invalid, but you are likely evaluating it before that logic is executed.
erquhart
erquhart3mo ago
For a Next project with SSR and Convex Auth latest version, I do see this as well, specifically when I haven't touched the project in some time, so something with the refresh. If I switch tabs for a second and come back, it resolves (not sure if something is happening with the tab switching or if it's just time).
No description
Heath
Heath3mo ago
I see this too in our project
sshader
sshader3mo ago
For a Next project with SSR and Convex Auth latest version, I do see this as well, specifically when I haven't touched the project in some time
Hmm this is surprising for latest version of Convex Auth (this error message in particular). For folks with custom middleware handlers, make sure you're using convexAuth.isAuthenticated and convexAuth.getToken in the handler (see https://labs.convex.dev/auth/authz/nextjs#require-authentication-for-certain-routes) (I also want to call out that Convex Auth + Next.js SSA support is still experimental, so bug reports + patience while we address those is much appreciated)
Server-side authentication in Next.js - Convex Auth
Authentication library for your Convex backend
erquhart
erquhart3mo ago
├── @convex-dev/auth@0.0.71 │ └── @auth/core@0.31.0 Just ran dev server first time today, which is when it reliably happens, still happening.
lexcodeit
lexcodeit3mo ago
I'm using "@convex-dev/auth": "^0.0.69", "convex": "^1.16.2" I managed to just clear cookies manually whenever I run into the issue for now till I figure a better way out.
allen
allen3mo ago
0.0.71 does have some improvements. 69 was especially problematic for me. The behavior I'm observing is the session getting nuked because an invalidate refresh token is used, which causes all cookies to be deleted.
erquhart
erquhart3mo ago
When you get the error, if you refresh the page it resolves right? That's what I'm seeing. I don't rely on cookies outside of whatever convex auth might be using, so that may limit the impact in my case.
allen
allen3mo ago
No. I'm logged out as my auth cookies are deleted.
erquhart
erquhart3mo ago
oh interesting, we're having different experiences then Mine is just on initial load, presumably a failed token refresh or something, but on refresh I'm still logged in

Did you find this page helpful?