From 047a6294213e75d6fd0cee92f7e3447e089f80e6 Mon Sep 17 00:00:00 2001 From: Dimitris Klouvas Date: Tue, 20 Jun 2023 17:11:35 +0300 Subject: [PATCH] fix(nextjs): Support using x-forwarded-* headers in req.nextUrl via env Introduced environment variable: CLERK_USE_X_FWD_HEADERS Provide `"true"` value to enable this. related NextJS issue: https://github.com/vercel/next.js/issues/37536 --- .changeset/nice-kangaroos-teach.md | 5 +++++ packages/nextjs/src/server/authMiddleware.ts | 21 ++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .changeset/nice-kangaroos-teach.md diff --git a/.changeset/nice-kangaroos-teach.md b/.changeset/nice-kangaroos-teach.md new file mode 100644 index 00000000000..2e99840ba78 --- /dev/null +++ b/.changeset/nice-kangaroos-teach.md @@ -0,0 +1,5 @@ +--- +'@clerk/nextjs': patch +--- + +Support non-Vercel platforms to override hostname of the url to fix the `localhost:3000` redirect from authMiddleware diff --git a/packages/nextjs/src/server/authMiddleware.ts b/packages/nextjs/src/server/authMiddleware.ts index 458ac6335eb..c98ad7b6431 100644 --- a/packages/nextjs/src/server/authMiddleware.ts +++ b/packages/nextjs/src/server/authMiddleware.ts @@ -67,7 +67,7 @@ type BeforeAuthHandler = ( ) => NextMiddlewareResult | Promise | false | Promise; type AfterAuthHandler = ( - auth: AuthObject & { isPublicRoute: boolean }, + auth: AuthObject & { isPublicRoute: boolean; isApiRoute: boolean }, req: NextRequest, evt: NextFetchEvent, ) => NextMiddlewareResult | Promise; @@ -134,6 +134,9 @@ const authMiddleware: AuthMiddleware = (...args: unknown[]) => { logger.enable(); } + setClerkUrlInRequest(req); + const requestUrl = process.env.CLERK_USE_X_FWD_HEADERS !== 'true' ? req.clerkUrl : req.nextUrl; + logger.debug('URL debug', { url: req.nextUrl.href, method: req.method, headers: stringifyHeaders(req.headers) }); logger.debug('Options debug', { ...options, beforeAuth: !!beforeAuth, afterAuth: !!afterAuth }); @@ -215,7 +218,7 @@ const createDefaultAfterAuth = ( if (!auth.userId && !isPublicRoute(req) && isApiRoute(req)) { return apiEndpointUnauthorizedNextResponse(); } else if (!auth.userId && !isPublicRoute(req)) { - return redirectToSignIn({ returnBackUrl: req.url }); + return redirectToSignIn({ returnBackUrl: req.nextUrl.href }); } return NextResponse.next(); }; @@ -332,3 +335,17 @@ A bug that may have already been fixed in the latest version of Clerk NextJS pac How to resolve: -> Make sure you are using the latest version of '@clerk/nextjs' and 'next'. `; + +const setClerkUrlInRequest = (req: NextRequest) => { + const clerkUrl = req.nextUrl.clone(); + clerkUrl.protocol = getFirstValueFromHeader(req, 'x-forwarded-proto') ?? clerkUrl.protocol; + clerkUrl.host = getFirstValueFromHeader(req, 'x-forwarded-host') ?? clerkUrl.host; + clerkUrl.port = getFirstValueFromHeader(req, 'x-forwarded-port') ?? clerkUrl.port; + + Object.assign(req, { clerkUrl }); +}; + +const getFirstValueFromHeader = (req: NextRequest, key: string) => { + const value = req.headers.get(key); + return value?.split(',')[0]; +};