Server-side authentication in Next.js
You can set up your Next.js App Router app to have access to the authentication state on the server.
Setup
Make sure your React providers and middleware are correctly set up first.
Require authentication for certain routes
By default, all routes can be accessed without authenticating. You can configure
which routes require authentication in your middleware.ts
:
import {
convexAuthNextjsMiddleware,
createRouteMatcher,
isAuthenticatedNextjs,
nextjsMiddlewareRedirect,
} from "@convex-dev/auth/nextjs/server";
const isSignInPage = createRouteMatcher(["/signin"]);
const isProtectedRoute = createRouteMatcher(["/product(.*)"]);
export default convexAuthNextjsMiddleware((request) => {
if (isSignInPage(request) && isAuthenticatedNextjs()) {
return nextjsMiddlewareRedirect(request, "/product");
}
if (isProtectedRoute(request) && !isAuthenticatedNextjs()) {
return nextjsMiddlewareRedirect(request, "/signin");
}
});
export const config = {
// The following matcher runs middleware on all routes
// except static assets.
matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};
In general, you'll likely want to redirect when an unauthenticated user tries to access a route that requires authentication.
To do this, you can pass a function to convexAuthNextjsMiddleware
. This
function can also be used to compose other middleware behaviors.
Convex Auth provides an API and helper functions for implementing your middleware:
-
createRouteMatcher
is a helper function that uses the same syntax (opens in a new tab) as the middlewareconfig
. You call it with a list of glob patterns, and it returns a function that given theNextRequest
returns whether the route matches. -
isAuthenticatedNextjs
function returns whether the current request is authenticated or not. When usingConvexAuthNextjsServerProvider
, authentication state is stored both in http-only cookies and on the client, so this state is also available during page requests. -
nextjsMiddlewareRedirect
is a simple shortcut for triggering redirects:export function nextjsMiddlewareRedirect( request: NextRequest, pathname: string, ) { const url = request.nextUrl.clone(); url.pathname = pathname; return NextResponse.redirect(url); }
You can inline this code if you need more control over the target URL.
Preloading and loading data
To preload or load data on your Next.js server from your Convex backend, you can
use
preloadQuery
and fetchQuery
(opens in a new tab)
and the convexAuthNextjsToken
function from @convex-dev/auth/nextjs/server
:
import { convexAuthNextjsToken } from "@convex-dev/auth/nextjs/server";
import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import { Tasks } from "./Tasks";
export async function TasksWrapper() {
const preloadedTasks = await preloadQuery(
api.tasks.list,
{ list: "default" },
{ token: convexAuthNextjsToken() },
);
return <Tasks preloadedTasks={preloadedTasks} />;
}
Calling authenticated mutations and actions
You can call Convex
mutations (opens in a new tab) and
actions (opens in a new tab) from Next.js
Server Actions (opens in a new tab)
and POST
or PUT
Route Handlers (opens in a new tab).
import { api } from "@/convex/_generated/api";
import { fetchMutation, fetchQuery } from "convex/nextjs";
import { revalidatePath } from "next/cache";
export default async function PureServerPage() {
const tasks = await fetchQuery(api.tasks.list, { list: "default" });
async function createTask(formData: FormData) {
"use server";
await fetchMutation(
api.tasks.create,
{
text: formData.get("text") as string,
},
{ token: convexAuthNextjsToken() },
);
revalidatePath("/example");
}
// render tasks and task creation form
return <form action={createTask}>...</form>;
}
Security notice: ConvexAuthNextjsServerProvider
uses cookies to store
authentication state. Therefore to prevent
CSRF attacks (opens in a new tab) you must not perform any
side-effects from the Next.js server on GET requests. This means that only
Convex queries are safe to call from Server Components and GET
Route Handlers.
Essentially, a malicious site might cause your user's browser to make an
authenticated GET
request without the user's permission, but it won't be able
to read the response. Outside of GET
requests, Convex Auth makes
authentication state available only to same-origin requests.
Convex Auth is not special here, and the same security considerations apply to most other authentication solutions.