Middleware
The ThunderID Next.js SDK provides Edge Runtime-compatible middleware for automatic token refresh and route protection.
thunderIDProxy()
Create a Next.js middleware that handles authentication concerns for every request.
import {
thunderIDProxy,
createRouteMatcher,
} from '@thunderid/nextjs/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])
export default thunderIDProxy(async (thunderid, request) => {
if (isProtectedRoute(request)) {
await thunderid.protectRoute()
}
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
Parameters
| Parameter | Type | Description |
|---|---|---|
handler | (thunderid, request) => Promise<void> | Optional callback that receives the auth context and the request |
options | ThunderIDProxyOptions | Optional configuration overrides |
ThunderIDProxyOptions accepts every ThunderIDNextConfig key, plus backchannelLogout.store, a LogoutRecordStore shared with backchannelLogout(). Set it when the application runs more than one instance, or when this middleware runs on the Edge runtime, which shares no memory with the route handler that records logouts.
Proxy Context
The thunderid object passed to your handler provides:
| Method | Return Type | Description |
|---|---|---|
getSession() | Promise<SessionTokenPayload | undefined> | Retrieve the current session payload |
getSessionId() | string | undefined | Retrieve the current session ID |
isSignedIn() | boolean | Check whether the user is authenticated |
protectRoute(options?) | Promise<NextResponse | void> | Redirect unauthenticated users to the sign-in page |
protectRoute() Options
| Option | Type | Description |
|---|---|---|
redirect | string | Custom URL to redirect unauthenticated users to. Defaults to the configured signInUrl |
createRouteMatcher()
Create a function that matches requests against a list of route patterns.
import { createRouteMatcher } from '@thunderid/nextjs/server'
const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/admin(.*)',
'/settings(.*)',
])
Parameters
| Parameter | Type | Description |
|---|---|---|
patterns | string[] | Array of glob-like route patterns |
Returns: (req: NextRequest) => boolean
Back-Channel Logout
The middleware treats a session that a back-channel logout ended as signed out, so isSignedIn() returns false and protectRoute() redirects. For the runtime and store this needs, see Requirements.
Automatic Token Refresh
The middleware automatically refreshes access tokens that are about to expire (within 25 seconds of their expiry). This happens transparently:
- The middleware reads the session cookie from the request
- If the token expires soon, the middleware calls the refresh endpoint
- The updated session cookie is set on both the response and the forwarded request headers
- Your page components and server actions always receive a valid token
Examples
Protect Multiple Route Groups
import {
thunderIDProxy,
createRouteMatcher,
} from '@thunderid/nextjs/server'
const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/settings(.*)',
'/api/private(.*)',
])
const isAdminRoute = createRouteMatcher(['/admin(.*)'])
export default thunderIDProxy(async (thunderid, request) => {
if (isAdminRoute(request)) {
await thunderid.protectRoute({ redirect: '/unauthorized' })
return
}
if (isProtectedRoute(request)) {
await thunderid.protectRoute()
}
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
Access Session Data in Middleware
import { thunderIDProxy } from '@thunderid/nextjs/server'
export default thunderIDProxy(async (thunderid, request) => {
const session = await thunderid.getSession()
if (session) {
console.log('Authenticated user:', session.sub)
}
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}