clerkMiddleware() | Nuxt
The clerkMiddleware()
helper allows you to protect your Nuxt application on the server-side. It can be used to validate a user's authentication status or authorization status.
Configure clerkMiddleware()
By default, the Nuxt SDK automatically adds the clerkMiddleware()
helper to your Nuxt application.
To manually configure the middleware:
-
In your
nuxt.config.ts
file, under theclerk
property, setskipServerMiddleware: true
.nuxt.config.ts export default defineNuxtConfig({ modules: ['@clerk/nuxt'], clerk: { skipServerMiddleware: true, }, })
-
In your
server/middleware/
directory, create a file namedclerk.ts
with the following code:server /middleware /clerk.ts import { clerkMiddleware } from '@clerk/nuxt/server' export default clerkMiddleware()
Protect API routes
You can protect API routes using either or both of the following:
- Authentication-based protection: Verify if the user is signed in.
- Authorization-based protection: Verify if the user has the required privileges, such as a role, permission, feature, or plan. Learn more about authorization checks.
You can also protect multiple routes using the createRouteMatcher()
helper.
Authentication-based protection
To protect routes based on user authentication status, you can check if the user is signed in by checking the isAuthenticated
property on the auth
object.
In the following example, the clerkMiddleware()
helper checks if the user is signed in and accessing a protected route. If they aren't signed in, an error is thrown using Nuxt's createError()
utility.
import { clerkMiddleware } from '@clerk/nuxt/server'
export default clerkMiddleware((event) => {
const { isAuthenticated } = event.context.auth()
const isAdminRoute = event.path.startsWith('/api/admin')
if (!isAuthenticated && isAdminRoute) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized: User not signed in',
})
}
})
Authorization-based protection
To protect routes based on user authorization status, you can use the has()
helper to check if the user has the required privileges, such as a role, permission, feature, or plan. The has()
helper is available on the auth
object.
Example: Protect routes based on custom permissions
In the following example, the clerkMiddleware()
helper checks if the user is accessing a protected route. If so, it checks if the user has the required custom permission. If they don't, an error is thrown using Nuxt's createError()
utility.
import { clerkMiddleware } from '@clerk/nuxt/server'
export default clerkMiddleware((event) => {
const { has } = event.context.auth()
const isInvoicesRoute = event.path.startsWith('/api/invoices')
const canCreateInvoices = has({
permission: 'org:invoices:create',
})
// Check if the user is accessing a protected route
if (isInvoicesRoute) {
// Check if the user has the required permission
if (!canCreateInvoices) {
throw createError({
statusCode: 403,
statusMessage: 'Unauthorized: Missing permission to create invoices',
})
}
}
})
In the following example, the clerkMiddleware()
helper checks if the user is accessing a protected route. If so, it checks if the user has the required admin role. If they don't, an error is thrown using Nuxt's createError()
utility.
import { clerkMiddleware } from '@clerk/nuxt/server'
export default clerkMiddleware((event) => {
const { has } = event.context.auth()
const isAdminRoute = event.path.startsWith('/api/admin')
const isAdmin = has({
role: 'org:admin',
})
// Check if the user is accessing a protected route
if (isAdminRoute) {
// Check if the user has the required role
if (!isAdmin) {
throw createError({
statusCode: 403,
statusMessage: 'Unauthorized: Admin access required',
})
}
}
})
Protect multiple routes
You can protect multiple routes at once by using Clerk's createRouteMatcher()
helper function. The createRouteMatcher()
helper accepts an array of route patterns and checks if the route the user is trying to visit matches one of the patterns passed to it.
Let's take the first example from this guide and add the createRouteMatcher()
helper. Instead of only checking /api/admin/**
routes, the following example checks both /api/invoices/**
and /api/admin/**
routes.
import { clerkMiddleware, createRouteMatcher } from '@clerk/nuxt/server'
export default clerkMiddleware((event) => {
const { isAuthenticated } = event.context.auth()
const isAdminRoute = event.path.startsWith('/api/admin')
const isProtectedRoute = createRouteMatcher(['/api/invoices(.*)', '/api/admin(.*)'])
// Check if the user is not signed in
// and is trying to access a protected route. If so, throw a 401 error.
if (!isAuthenticated && isProtectedRoute(event)) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized: User not signed in',
})
}
})
Now, let's add authorization-based protection to the example so that you can see how to combine everything you've learned so far.
import { clerkMiddleware, createRouteMatcher } from '@clerk/nuxt/server'
export default clerkMiddleware((event) => {
const { isAuthenticated } = event.context.auth()
const isProtectedRoute = createRouteMatcher(['/api/invoices(.*)', '/api/admin(.*)'])
const canCreateInvoices = has({
permission: 'org:invoices:create',
})
// Check if the user is not signed in
// and is trying to access a protected route. If so, throw a 401 error.
if (!isAuthenticated && isProtectedRoute(event)) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized: User not signed in',
})
}
// Check if the user doesn't have the required permission
// and is accessing a protected route. If so, throw a 403 error.
if (!canCreateInvoices && isProtectedRoute(event)) {
throw createError({
statusCode: 403,
statusMessage: 'Unauthorized: Missing permission to create invoices',
})
}
})
Feedback
Last updated on