Middleware
authMiddleware
We have launched a new version of the middleware that is compatible with both the stable version of next.js (with /pages) and the App Router (with /app).
Copy this snippet into a file named middleware.js or middleware.ts in your project root.
middleware.ts1import { authMiddleware } from "@clerk/nextjs";23export default authMiddleware();45export const config = {6matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],7};
Execution order of beforeAuth, publicRoutes and afterAuth
If you define an afterAuth
function, it will run even if the request corresponds to a private route and no user is signed out.
If you don’t define an afterAuth
, a redirect response to the signInUrl will be returned automatically.
This is a diagram that explains how and when the two handlers are invoked in the runtime.
Using afterAuth for fine grain control
Some developers will need to handle specific cases such as detecting if the user is inside and organization, or handle redirects differently. You can do that by using afterAuth
1export default authMiddleware({2afterAuth(auth, req, evt) {3// handle users who aren't authenticated4if (!auth.userId && !auth.isPublicRoute) {5const signInUrl = new URL('/sign-in', req.url)6signInUrl.searchParams.set('redirect_url', req.url)7return NextResponse.redirect(signInUrl)8}9// rededirect them to organization selection page10if(!auth.orgId){11const orgSelection = new URL('/org-selection', req.url)12return NextResponse.redirect(orgSelection)13}14},15});
Chaining Middleware together
If you need to chain middleware's together you can do so by using the beforeAuth
if you need it to happen before Clerk. Below is an example of Clerk & next-intl.
middleware.ts1import { authMiddleware } from "@clerk/nextjs";23import createMiddleware from "next-intl/middleware";45const intlMiddleware = createMiddleware({6locales: ["en", "el"],78defaultLocale: "en",9});1011export default authMiddleware({12beforeAuth: (req) => {13return intlMiddleware(req);14},1516publicRoutes: ["/", "/:locale/sign-in"],17});1819export const config = {20matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],21};22
Making pages public using publicRoutes
Below is an example of using `publicRoutes` to handle pages that should be accessible to users when they are not logged in.
1import { authMiddleware } from "@clerk/nextjs";2export default authMiddleware({3publicRoutes: ["/"]4});56export const config = {7matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],8};
If you are building your own sign in pages, you don't need to add them to your publicRoutes. You can add them to your `.env`
1NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in2NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up3NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/4NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
Middleware argument types
Previous versions
withClerkMiddleware
This is our previous version of middleware and will soon be deprecated.
Copy this snippet into a file named middleware.js or middleware.ts in your project root.
1import { withClerkMiddleware } from "@clerk/nextjs/server";2import { NextResponse } from "next/server";34export default withClerkMiddleware((req) => {5return NextResponse.next();6});78// Stop Middleware running on static files9export const config = { matcher: '/((?!_next/image|_next/static|favicon.ico).*)',};
1import { withClerkMiddleware } from "@clerk/nextjs/server";2import { NextResponse } from "next/server";3import type { NextRequest } from 'next/server'45export default withClerkMiddleware((req: NextRequest) => {6return NextResponse.next();7});89// Stop Middleware running on static files10export const config = { matcher: '/((?!_next/image|_next/static|favicon.ico).*)',};11
1import { withClerkMiddleware, getAuth } from '@clerk/nextjs/server'2import { NextResponse } from 'next/server'3import type { NextRequest } from 'next/server'45// Set the paths that don't require the user to be signed in6const publicPaths = ['/', '/sign-in*', '/sign-up*']78const isPublic = (path: string) => {9return publicPaths.find(x =>10path.match(new RegExp(`^${x}$`.replace('*$', '($|/)')))11)12}1314export default withClerkMiddleware((request: NextRequest) => {15if (isPublic(request.nextUrl.pathname)) {16return NextResponse.next()17}18// if the user is not signed in redirect them to the sign in page.19const { userId } = getAuth(request)2021if (!userId) {22// redirect the users to /pages/sign-in/[[...index]].ts2324const signInUrl = new URL('/sign-in', request.url)25signInUrl.searchParams.set('redirect_url', request.url)26return NextResponse.redirect(signInUrl)27}28return NextResponse.next()29})3031export const config = { matcher: '/((?!_next/image|_next/static|favicon.ico).*)',};
Clerk only depends on the withClerkMiddleware()
wrapper. You are welcome to customize the internal middleware function as needed.
Before Next.js 12.2
Using the withEdgeMiddlewareAuth
wrapper you can access authentication data
1import { withEdgeMiddlewareAuth } from "@clerk/nextjs/edge-middleware";23export default withEdgeMiddlewareAuth(async req => {4const { userId, sessionId, getToken } = req.auth;5const supabaseToken = await getToken({ template: 'supabase' })6// Run your middleware78// Complete response9return NextResponse.next();10});
1import { withEdgeMiddlewareAuth } from '@clerk/nextjs/edge-middleware'2import { NextResponse, NextRequest } from 'next/server'3import { ServerGetToken } from '@clerk/types'45//example usage of interfaces with Clerk6interface ClerkRequest extends NextRequest {7auth: {8userId?: string | null9sessionId?: string | null10getToken: ServerGetToken11}12}1314export default withEdgeMiddlewareAuth(async (req: ClerkRequest) => {15const { userId, sessionId, getToken } = req.auth16const supabaseToken = await getToken({ template: 'supabase' })17// Load any data your application needs for the API route18return NextResponse.next();19})
Example Response
{sessionId: 'sess_2GaMqUCB3Sc1WNAkWuNzsnYVVEy',userId: 'user_2F2u1wtUyUlxKgFkKqtJNtpJJWj',orgId: null,getToken: [AsyncFunction (anonymous)],claims: {azp: 'http://localhost:3000',exp: 1666622607,iat: 1666622547,iss: 'https://clerk.quiet.muskox-85.lcl.dev',nbf: 1666622537,sid: 'sess_2GaMqUCB3Sc1WNAkWuNzsnYVVEy',sub: 'user_2F2u1wtUyUlxKgFkKqtJNtpJJWj'}}
More detailed information about the fields in this object can be found in the Authentication Object documentation.