@@ -4,7 +4,7 @@ import type { AuthObject, ClerkClient } from '@clerk/backend';
44import type { AuthenticateRequestOptions , ClerkRequest , RedirectFun , RequestState } from '@clerk/backend/internal' ;
55import { AuthStatus , constants , createClerkRequest , createRedirect } from '@clerk/backend/internal' ;
66import { eventMethodCalled } from '@clerk/shared/telemetry' ;
7- import type { NextMiddleware } from 'next/server' ;
7+ import type { NextMiddleware , NextRequest } from 'next/server' ;
88import { NextResponse } from 'next/server' ;
99
1010import { isRedirect , serverRedirectWithAuth , setHeader } from '../utils' ;
@@ -44,6 +44,8 @@ type ClerkMiddlewareHandler = (
4444
4545export type ClerkMiddlewareOptions = AuthenticateRequestOptions & { debug ?: boolean } ;
4646
47+ type ClerkMiddlewareOptionsCallback = ( req : NextRequest ) => ClerkMiddlewareOptions ;
48+
4749/**
4850 * Middleware for Next.js that handles authentication and authorization with Clerk.
4951 * For more details, please refer to the docs: https://clerk.com/docs/references/nextjs/clerk-middleware
@@ -54,6 +56,11 @@ interface ClerkMiddleware {
5456 * export default clerkMiddleware((auth, request, event) => { ... }, options);
5557 */
5658 ( handler : ClerkMiddlewareHandler , options ?: ClerkMiddlewareOptions ) : NextMiddleware ;
59+ /**
60+ * @example
61+ * export default clerkMiddleware((auth, request, event) => { ... }, (req) => options);
62+ */
63+ ( handler : ClerkMiddlewareHandler , options ?: ClerkMiddlewareOptionsCallback ) : NextMiddleware ;
5764 /**
5865 * @example
5966 * export default clerkMiddleware(options);
@@ -66,38 +73,47 @@ interface ClerkMiddleware {
6673 ( request : NextMiddlewareRequestParam , event : NextMiddlewareEvtParam ) : NextMiddlewareReturn ;
6774}
6875
69- export const clerkMiddlewareRequestDataStore = new AsyncLocalStorage < Partial < AuthenticateRequestOptions > > ( ) ;
76+ const clerkMiddlewareRequestDataStore = new Map < 'requestData' , AuthenticateRequestOptions > ( ) ;
77+ export const clerkMiddlewareRequestDataStorage = new AsyncLocalStorage < typeof clerkMiddlewareRequestDataStore > ( ) ;
7078
7179export const clerkMiddleware : ClerkMiddleware = ( ...args : unknown [ ] ) : any => {
7280 const [ request , event ] = parseRequestAndEvent ( args ) ;
7381 const [ handler , params ] = parseHandlerAndOptions ( args ) ;
7482
75- const publishableKey = assertKey ( params . publishableKey || PUBLISHABLE_KEY , ( ) =>
76- errorThrower . throwMissingPublishableKeyError ( ) ,
77- ) ;
78- const secretKey = assertKey ( params . secretKey || SECRET_KEY , ( ) => errorThrower . throwMissingSecretKeyError ( ) ) ;
79- const signInUrl = params . signInUrl || SIGN_IN_URL ;
80- const signUpUrl = params . signUpUrl || SIGN_UP_URL ;
81-
82- const options = {
83- ...params ,
84- publishableKey,
85- secretKey,
86- signInUrl,
87- signUpUrl,
88- } ;
83+ return clerkMiddlewareRequestDataStorage . run ( clerkMiddlewareRequestDataStore , ( ) => {
84+ const nextMiddleware : NextMiddleware = withLogger ( 'clerkMiddleware' , logger => async ( request , event ) => {
85+ // Handles the case where `options` is a callback function to dynamically access `NextRequest`
86+ const resolvedParams = typeof params === 'function' ? params ( request ) : params ;
8987
90- return clerkMiddlewareRequestDataStore . run ( options , ( ) => {
91- clerkClient ( ) . telemetry . record (
92- eventMethodCalled ( 'clerkMiddleware' , {
93- handler : Boolean ( handler ) ,
94- satellite : Boolean ( options . isSatellite ) ,
95- proxy : Boolean ( options . proxyUrl ) ,
96- } ) ,
97- ) ;
88+ const publishableKey = assertKey ( resolvedParams . publishableKey || PUBLISHABLE_KEY , ( ) =>
89+ errorThrower . throwMissingPublishableKeyError ( ) ,
90+ ) ;
91+ const secretKey = assertKey ( resolvedParams . secretKey || SECRET_KEY , ( ) =>
92+ errorThrower . throwMissingSecretKeyError ( ) ,
93+ ) ;
94+ const signInUrl = resolvedParams . signInUrl || SIGN_IN_URL ;
95+ const signUpUrl = resolvedParams . signUpUrl || SIGN_UP_URL ;
96+
97+ const options = {
98+ publishableKey,
99+ secretKey,
100+ signInUrl,
101+ signUpUrl,
102+ ...resolvedParams ,
103+ } ;
104+
105+ // Propagates the request data to be accessed on the server application runtime from helpers such as `clerkClient`
106+ clerkMiddlewareRequestDataStore . set ( 'requestData' , options ) ;
107+
108+ clerkClient ( ) . telemetry . record (
109+ eventMethodCalled ( 'clerkMiddleware' , {
110+ handler : Boolean ( handler ) ,
111+ satellite : Boolean ( options . isSatellite ) ,
112+ proxy : Boolean ( options . proxyUrl ) ,
113+ } ) ,
114+ ) ;
98115
99- const nextMiddleware : NextMiddleware = withLogger ( 'clerkMiddleware' , logger => async ( request , event ) => {
100- if ( params . debug ) {
116+ if ( options . debug ) {
101117 logger . enable ( ) ;
102118 }
103119 const clerkRequest = createClerkRequest ( request ) ;
@@ -131,8 +147,9 @@ export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]): any => {
131147
132148 let handlerResult : Response = NextResponse . next ( ) ;
133149 try {
134- const userHandlerResult = await clerkMiddlewareRequestDataStore . run ( options , async ( ) =>
135- handler ?.( ( ) => authObjWithMethods , request , event ) ,
150+ const userHandlerResult = await clerkMiddlewareRequestDataStorage . run (
151+ clerkMiddlewareRequestDataStore ,
152+ async ( ) => handler ?.( ( ) => authObjWithMethods , request , event ) ,
136153 ) ;
137154 handlerResult = userHandlerResult || handlerResult ;
138155 } catch ( e : any ) {
@@ -156,7 +173,7 @@ export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]): any => {
156173 setRequestHeadersOnNextResponse ( handlerResult , clerkRequest , { [ constants . Headers . EnableDebug ] : 'true' } ) ;
157174 }
158175
159- decorateRequest ( clerkRequest , handlerResult , requestState , params ) ;
176+ decorateRequest ( clerkRequest , handlerResult , requestState , resolvedParams ) ;
160177
161178 return handlerResult ;
162179 } ) ;
@@ -184,7 +201,7 @@ const parseHandlerAndOptions = (args: unknown[]) => {
184201 return [
185202 typeof args [ 0 ] === 'function' ? args [ 0 ] : undefined ,
186203 ( args . length === 2 ? args [ 1 ] : typeof args [ 0 ] === 'function' ? { } : args [ 0 ] ) || { } ,
187- ] as [ ClerkMiddlewareHandler | undefined , ClerkMiddlewareOptions ] ;
204+ ] as [ ClerkMiddlewareHandler | undefined , ClerkMiddlewareOptions | ClerkMiddlewareOptionsCallback ] ;
188205} ;
189206
190207type AuthenticateRequest = Pick < ClerkClient , 'authenticateRequest' > [ 'authenticateRequest' ] ;
0 commit comments