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',
})
}
})
clerkMiddleware()
options
The clerkMiddleware()
function accepts an optional object. The following options are available:
- Name
audience?
- Type
string | string[]
- Description
A string or list of audiences. If passed, it is checked against the
aud
claim in the token.
- Name
authorizedParties?
- Type
string[]
- Description
An allowlist of origins to verify against, to protect your application from the subdomain cookie leaking attack. For example:
['http://localhost:3000', 'https://example.com']
- Name
clockSkewInMs?
- Type
number
- Description
Specifies the allowed time difference (in milliseconds) between the Clerk server (which generates the token) and the clock of the user's application server when validating a token. Defaults to 5000 ms (5 seconds).
- Name
domain?
- Type
string
- Description
The domain used for satellites to inform Clerk where this application is deployed.
- Name
isSatellite?
- Type
boolean
- Description
When using Clerk's satellite feature, this should be set to
true
for secondary domains.
- Name
jwtKey
- Type
string
- Description
Used to verify the session token in a networkless manner. Supply the JWKS Public Key from the API keys page in the Clerk Dashboard. It's recommended to use the environment variable instead. For more information, refer to Manual JWT verification.
- Name
organizationSyncOptions?
- Type
OrganizationSyncOptions | undefined
- Description
Used to activate a specific organization or personal account based on URL path parameters. If there's a mismatch between the in the session (e.g., as reported by ) and the organization indicated by the URL, the middleware will attempt to activate the organization specified in the URL.
- Name
proxyUrl?
- Type
string
- Description
Specify the URL of the proxy, if using a proxy.
- Name
signInUrl
- Type
string
- Description
The full URL or path to your sign-in page. Needs to point to your primary application on the client-side. Required for a satellite application in a development instance. It's recommended to use the environment variable instead.
- Name
signUpUrl
- Type
string
- Description
The full URL or path to your sign-up page. Needs to point to your primary application on the client-side. Required for a satellite application in a development instance. It's recommended to use the environment variable instead.
- Name
publishableKey
- Type
string
- Description
The Clerk Publishable Key for your instance. This can be found on the API keys page in the Clerk Dashboard.
- Name
secretKey?
- Type
string
- Description
The Clerk Secret Key for your instance. This can be found on the API keys page in the Clerk Dashboard. The
CLERK_ENCRYPTION_KEY
environment variable must be set when providingsecretKey
as an option, refer to Dynamic keys.
OrganizationSyncOptions
The organizationSyncOptions
property on the clerkMiddleware()
options
object has the type OrganizationSyncOptions
, which has the following properties:
- Name
organizationPatterns
- Type
Pattern[]
- Description
Specifies URL patterns that are organization-specific, containing an organization ID or slug as a path parameter. If a request matches this path, the organization identifier will be used to set that org as active.
If the route also matches the
personalAccountPatterns
prop, this prop takes precedence.Patterns must have a path parameter named either
:id
(to match a Clerk organization ID) or:slug
(to match a Clerk organization slug).Common examples:
["/orgs/:slug", "/orgs/:slug/(.*)"]
["/orgs/:id", "/orgs/:id/(.*)"]
["/app/:any/orgs/:slug", "/app/:any/orgs/:slug/(.*)"]
- Name
personalAccountPatterns
- Type
Pattern[]
- Description
URL patterns for resources that exist within the context of a user's personal account.
If the route also matches the
organizationPattern
prop, theorganizationPattern
prop takes precedence.Common examples:
["/me", "/me/(.*)"]
["/user/:any", "/user/:any/(.*)"]
Pattern
A Pattern
is a string
that represents the structure of a URL path. In addition to any valid URL, it may include:
- Named path parameters prefixed with a colon (e.g.,
:id
,:slug
,:any
). - Wildcard token,
(.*)
, which matches the remainder of the path.
Examples
/orgs/:slug
/app/:any/orgs/:id
/personal-account/(.*)
Feedback
Last updated on