#logs are not very description for an auth issue: 'Invalid verifier' - Issue is nextjs middleware.ts
20 messages · Page 1 of 1 (latest)
I thought i'd create a thread for this originally I was just getting these errors
9/1/2025, 5:08:19 PM [CONVEX M(auth:store)] [INFO] '`auth:store` type: verifier'
9/1/2025, 5:08:19 PM [CONVEX M(auth:store)] [INFO] '`auth:store` type: verifierSignature'
9/1/2025, 5:08:39 PM [CONVEX M(auth:store)] [INFO] '`auth:store` type: userOAuth'
9/1/2025, 5:08:39 PM [CONVEX M(auth:store)] [INFO] '`auth:store` type: verifyCodeAndSignIn'
9/1/2025, 5:08:39 PM [CONVEX M(auth:store)] [ERROR] 'Invalid verifier'
wasn't sure why I started getting these and had to backtrack a bit to find out why.
The "invalid verifier" didn't really help me find out why, turns out having a middleware.ts, copied exactly from https://labs.convex.dev/auth/authz/nextjs, or not having the middleware.ts is the differentiator between working auth and not working auth that throws the error above.
import {
convexAuthNextjsMiddleware,
createRouteMatcher,
nextjsMiddlewareRedirect,
} from "@convex-dev/auth/nextjs/server";
const isSignInPage = createRouteMatcher(["/sign-in"]);
const isProtectedRoute = createRouteMatcher(["/dashboard(.*)"]);
export default convexAuthNextjsMiddleware(async (request, { convexAuth }) => {
if (isSignInPage(request) && (await convexAuth.isAuthenticated())) {
return nextjsMiddlewareRedirect(request, "/product");
}
if (isProtectedRoute(request) && !(await convexAuth.isAuthenticated())) {
return nextjsMiddlewareRedirect(request, "/sign-in");
}
});
export const config = {
// The following matcher runs middleware on all routes
// except static assets.
matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};
logs are not very description for an auth issue: 'Invalid verifier' - Issue is nextjs middleware.ts
Originally my middleware had custom logic for redirecting users around as I needed, but I copied it exactly to whats in the docs to remove extra variables
Are you saying that this middleware caused the error, or removing it caused the error? Trying to understand actual vs expected
having the middleware causes the issue to happen @floral mountain
not having it allows me to log in correctly
More details include:
I am using discord oauth, I havent tried other login methods
as a work around I am using a client-side "middleware" to navigate me around based on auth state. It's janky but works for now.
Can you share your ConvexClientProvider.tsx and your root layout
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexAuthProvider } from "@convex-dev/auth/react";
const convexUrl =
process.env.NEXT_PUBLIC_CONVEX_URL;
if (!convexUrl) {
throw new Error(
"Convex URL missing. Set NEXT_PUBLIC_CONVEX_URL.",
);
}
const convex = new ConvexReactClient(convexUrl);
export default function ConvexClientProvider({
children,
}: {
children: ReactNode;
}) {
return <ConvexAuthProvider client={convex}>{children}</ConvexAuthProvider>;
}
import "./globals.css";
import type { Metadata } from "next";
import { Geist_Mono, Plus_Jakarta_Sans, Baloo_2 } from "next/font/google";
import ConvexClientProvider from "../../../../components/ConvexClientProvider";
import { Background } from "../components/Background";
import TopNav from "../components/TopNav";
const plusJakarta = Plus_Jakarta_Sans({
variable: "--font-geist-sans",
subsets: ["latin"],
display: "swap",
fallback: [
"Zen Kaku Gothic New",
"Hiragino Kaku Gothic ProN",
"Yu Gothic",
"Meiryo",
"system-ui",
"sans-serif",
],
});
const baloo = Baloo_2({
variable: "--font-display",
subsets: ["latin"],
weight: "500",
display: "swap",
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/lipis/[email protected]/css/flag-icons.min.css"
/>
</head>
<body
suppressHydrationWarning
className={`${plusJakarta.variable} ${geistMono.variable} ${baloo.variable} antialiased`}
>
<ConvexClientProvider>
<div className="min-h-screen px-4 max-w-7xl mx-auto">
<Background />
<TopNav />
{children}
</div>
</ConvexClientProvider>
</body>
</html>
);
}
Did these change since you were hitting those errors or is this how they've been
the only change was that ConvexCleintProvider used to have a ?? for the EXPO_PUBLIC_CONVEX_URL
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexAuthProvider } from "@convex-dev/auth/react";
const convexUrl =
process.env.NEXT_PUBLIC_CONVEX_URL ?? process.env.EXPO_PUBLIC_CONVEX_URL;
if (!convexUrl) {
throw new Error(
"Convex URL missing. Set NEXT_PUBLIC_CONVEX_URL (web) or EXPO_PUBLIC_CONVEX_URL (mobile).",
);
}
const convex = new ConvexReactClient(convexUrl);
export default function ConvexClientProvider({
children,
}: {
children: ReactNode;
}) {
return <ConvexAuthProvider client={convex}>{children}</ConvexAuthProvider>;
}
heres the old version
its likely unrelated, but it is the only change.
You're only using the react client, so your setup won't be compatible with middleware or anything that requires server side auth.
If you want to use middleware and SSA in general, you'll want to follow the steps for that in the docs.
Go here: https://labs.convex.dev/auth/setup#set-up-the-react-provider
Make sure to select "Next.js" and "App Router with SSA".