From 640d458b1a745a96345229c0bcdaa935cd6d39d5 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 10:47:08 -0800 Subject: [PATCH 01/11] fix(astro): Temporary fix to redirect loop with Netlify adapter --- packages/astro/src/integration/create-integration.ts | 10 ++++++++++ packages/astro/src/server/clerk-middleware.ts | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 70099d62d15..5a4d1723f21 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -111,6 +111,16 @@ function createIntegration() ${command === 'dev' ? `console.log("${packageName}","Initialize Clerk: page")` : ''} import { runInjectionScript, swapDocument } from "${buildImportPath}"; + function removeTemporaryNetlifyClerkQueryParam(param) { + const url = new URL(window.location.href); + if (url.searchParams.has(param)) { + url.searchParams.delete(param); + window.history.replaceState(window.history.state, '', url); + } + } + + removeTemporaryNetlifyClerkQueryParam('__netlify_clerk_cache_bust'); + // Taken from https://github.com/withastro/astro/blob/e10b03e88c22592fbb42d7245b65c4f486ab736d/packages/astro/src/transitions/router.ts#L39. // Importing it directly from astro:transitions/client breaks custom client-side routing // even when View Transitions is disabled. diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index 3bdf0a53cf0..e73aa07edea 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -83,6 +83,12 @@ export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]): any => { const locationHeader = requestState.headers.get(constants.Headers.Location); if (locationHeader) { + if (!locationHeader.includes('client/handshake') && !locationHeader.includes('__clerk_handshake')) { + const url = new URL(locationHeader); + url.searchParams.append('__netlify_clerk_cache_bust', Date.now().toString()); + requestState.headers.set('Location', url.toString()); + } + const res = new Response(null, { status: 307, headers: requestState.headers }); return decorateResponseWithObservabilityHeaders(res, requestState); } else if (requestState.status === AuthStatus.Handshake) { From a8cba42eb9eaa0a53fd0a054ff0cd7fb5f529dd4 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 15:51:08 -0800 Subject: [PATCH 02/11] chore(astro): Clean up variable names --- .../astro/src/integration/create-integration.ts | 4 ++-- packages/astro/src/server/clerk-middleware.ts | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 5a4d1723f21..909004fdd17 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -111,7 +111,7 @@ function createIntegration() ${command === 'dev' ? `console.log("${packageName}","Initialize Clerk: page")` : ''} import { runInjectionScript, swapDocument } from "${buildImportPath}"; - function removeTemporaryNetlifyClerkQueryParam(param) { + function removeClerkQueryParam(param) { const url = new URL(window.location.href); if (url.searchParams.has(param)) { url.searchParams.delete(param); @@ -119,7 +119,7 @@ function createIntegration() } } - removeTemporaryNetlifyClerkQueryParam('__netlify_clerk_cache_bust'); + removeClerkQueryParam('__netlify_clerk_cache_bust'); // Taken from https://github.com/withastro/astro/blob/e10b03e88c22592fbb42d7245b65c4f486ab736d/packages/astro/src/transitions/router.ts#L39. // Importing it directly from astro:transitions/client breaks custom client-side routing diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index e73aa07edea..86bfbde8b54 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -81,13 +81,10 @@ export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]): any => { createAuthenticateRequestOptions(clerkRequest, options, context), ); + console.log('requestState', requestState); const locationHeader = requestState.headers.get(constants.Headers.Location); if (locationHeader) { - if (!locationHeader.includes('client/handshake') && !locationHeader.includes('__clerk_handshake')) { - const url = new URL(locationHeader); - url.searchParams.append('__netlify_clerk_cache_bust', Date.now().toString()); - requestState.headers.set('Location', url.toString()); - } + handleNetlifyCacheInDevInstance(locationHeader, requestState); const res = new Response(null, { status: 307, headers: requestState.headers }); return decorateResponseWithObservabilityHeaders(res, requestState); @@ -240,6 +237,16 @@ Check if signInUrl is missing from your configuration or if it is not an absolut PUBLIC_CLERK_SIGN_IN_URL='SOME_URL' PUBLIC_CLERK_IS_SATELLITE='true'`; +function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { + const isHandshakeUrl = locationHeader.includes('/v1/client/handshake'); + const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); + if (!isHandshakeUrl && !hasHandshakeQueryParam) { + const url = new URL(locationHeader); + url.searchParams.append('__netlify_clerk_cache_bust', Date.now().toString()); + requestState.headers.set('Location', url.toString()); + } +} + function decorateAstroLocal(clerkRequest: ClerkRequest, context: APIContext, requestState: RequestState) { const { reason, message, status, token } = requestState; context.locals.authToken = token; From ecfa7d3ca7cf1577d2a9fb62272d52f46f055d3b Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 16:05:29 -0800 Subject: [PATCH 03/11] chore(astro): Improve names --- .../astro/src/integration/create-integration.ts | 13 +++---------- packages/astro/src/internal/index.ts | 1 + packages/astro/src/internal/remove-query-param.ts | 13 +++++++++++++ packages/astro/src/server/clerk-middleware.ts | 7 ++++++- 4 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 packages/astro/src/internal/remove-query-param.ts diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 909004fdd17..5d2c1787fd5 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -109,17 +109,10 @@ function createIntegration() 'page', ` ${command === 'dev' ? `console.log("${packageName}","Initialize Clerk: page")` : ''} - import { runInjectionScript, swapDocument } from "${buildImportPath}"; - - function removeClerkQueryParam(param) { - const url = new URL(window.location.href); - if (url.searchParams.has(param)) { - url.searchParams.delete(param); - window.history.replaceState(window.history.state, '', url); - } - } + import { removeNetlifyCacheBustParam, runInjectionScript, swapDocument } from "${buildImportPath}"; - removeClerkQueryParam('__netlify_clerk_cache_bust'); + // Fix an issue with infinite reload in Netlify and Clerk dev instance + removeNetlifyCacheBustParam(); // Taken from https://github.com/withastro/astro/blob/e10b03e88c22592fbb42d7245b65c4f486ab736d/packages/astro/src/transitions/router.ts#L39. // Importing it directly from astro:transitions/client breaks custom client-side routing diff --git a/packages/astro/src/internal/index.ts b/packages/astro/src/internal/index.ts index 24c1b6670a9..47ba4bf14ab 100644 --- a/packages/astro/src/internal/index.ts +++ b/packages/astro/src/internal/index.ts @@ -14,3 +14,4 @@ export { runInjectionScript }; export { generateSafeId } from './utils/generateSafeId'; export { swapDocument } from './swap-document'; +export { NETLIFY_CACHE_BUST_PARAM, removeNetlifyCacheBustParam } from './remove-query-param'; diff --git a/packages/astro/src/internal/remove-query-param.ts b/packages/astro/src/internal/remove-query-param.ts new file mode 100644 index 00000000000..18624d8657c --- /dev/null +++ b/packages/astro/src/internal/remove-query-param.ts @@ -0,0 +1,13 @@ +export const NETLIFY_CACHE_BUST_PARAM = '__netlify_clerk_cache_bust'; + +/** + * Removes the temporary cache bust parameter that prevents infinite redirects + * in Netlify and Clerk's dev instance. + */ +export function removeNetlifyCacheBustParam() { + const url = new URL(window.location.href); + if (url.searchParams.has(NETLIFY_CACHE_BUST_PARAM)) { + url.searchParams.delete(NETLIFY_CACHE_BUST_PARAM); + window.history.replaceState(window.history.state, '', url); + } +} diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index 86bfbde8b54..ac97334b1fe 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -10,6 +10,7 @@ import type { APIContext } from 'astro'; // @ts-ignore import { authAsyncStorage } from '#async-local-storage'; +import { NETLIFY_CACHE_BUST_PARAM } from '../internal'; import { buildClerkHotloadScript } from './build-clerk-hotload-script'; import { clerkClient } from './clerk-client'; import { createCurrentUser } from './current-user'; @@ -237,12 +238,16 @@ Check if signInUrl is missing from your configuration or if it is not an absolut PUBLIC_CLERK_SIGN_IN_URL='SOME_URL' PUBLIC_CLERK_IS_SATELLITE='true'`; +/** + * Adds a cache bust parameter to non-handshake redirects to prevent infinite redirects + * in Netlify and Clerk's dev instance. + */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { const isHandshakeUrl = locationHeader.includes('/v1/client/handshake'); const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); if (!isHandshakeUrl && !hasHandshakeQueryParam) { const url = new URL(locationHeader); - url.searchParams.append('__netlify_clerk_cache_bust', Date.now().toString()); + url.searchParams.append(NETLIFY_CACHE_BUST_PARAM, Date.now().toString()); requestState.headers.set('Location', url.toString()); } } From 3f694a419a5f961dc37bcde47ba01e3baffa0a87 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 17:02:58 -0800 Subject: [PATCH 04/11] chore(astro): Remove unnecessary param check --- packages/astro/src/integration/create-integration.ts | 2 +- packages/astro/src/server/clerk-middleware.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/integration/create-integration.ts b/packages/astro/src/integration/create-integration.ts index 5d2c1787fd5..8d24fbc05e2 100644 --- a/packages/astro/src/integration/create-integration.ts +++ b/packages/astro/src/integration/create-integration.ts @@ -111,7 +111,7 @@ function createIntegration() ${command === 'dev' ? `console.log("${packageName}","Initialize Clerk: page")` : ''} import { removeNetlifyCacheBustParam, runInjectionScript, swapDocument } from "${buildImportPath}"; - // Fix an issue with infinite reload in Netlify and Clerk dev instance + // Fix an issue with infinite redirect in Netlify and Clerk dev instance removeNetlifyCacheBustParam(); // Taken from https://github.com/withastro/astro/blob/e10b03e88c22592fbb42d7245b65c4f486ab736d/packages/astro/src/transitions/router.ts#L39. diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index ac97334b1fe..2f56cb18db1 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -243,9 +243,8 @@ Check if signInUrl is missing from your configuration or if it is not an absolut * in Netlify and Clerk's dev instance. */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { - const isHandshakeUrl = locationHeader.includes('/v1/client/handshake'); const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); - if (!isHandshakeUrl && !hasHandshakeQueryParam) { + if (!hasHandshakeQueryParam) { const url = new URL(locationHeader); url.searchParams.append(NETLIFY_CACHE_BUST_PARAM, Date.now().toString()); requestState.headers.set('Location', url.toString()); From fad57de170793e5ba4e76f1e05811a1ae1bd9b2f Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 17:12:26 -0800 Subject: [PATCH 05/11] chore(astro): Add comment about handshake redirects --- packages/astro/src/server/clerk-middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index 2f56cb18db1..8a19e2af5d9 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -82,7 +82,6 @@ export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]): any => { createAuthenticateRequestOptions(clerkRequest, options, context), ); - console.log('requestState', requestState); const locationHeader = requestState.headers.get(constants.Headers.Location); if (locationHeader) { handleNetlifyCacheInDevInstance(locationHeader, requestState); @@ -244,6 +243,7 @@ Check if signInUrl is missing from your configuration or if it is not an absolut */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); + // If location header is the original URL before the handshake redirects, add cache bust param if (!hasHandshakeQueryParam) { const url = new URL(locationHeader); url.searchParams.append(NETLIFY_CACHE_BUST_PARAM, Date.now().toString()); From 7a38560719a7591ee176554d1407fccbfbbec143 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 17:15:58 -0800 Subject: [PATCH 06/11] chore(astro): Improve comments --- packages/astro/src/server/clerk-middleware.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index 8a19e2af5d9..d96df4b4954 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -238,8 +238,9 @@ Check if signInUrl is missing from your configuration or if it is not an absolut PUBLIC_CLERK_IS_SATELLITE='true'`; /** - * Adds a cache bust parameter to non-handshake redirects to prevent infinite redirects - * in Netlify and Clerk's dev instance. + * Prevents infinite redirects in Netlify's functions + * by adding a cache bust parameter to the original redirect URL. This ensures Netlify + * doesn't serve a cached response during the authentication flow. */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); From 8f8401deda7ef0d2837dd3a1b570bc659e734dce Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Mon, 9 Dec 2024 17:26:36 -0800 Subject: [PATCH 07/11] chore(astro): Only run fix on netlify env --- packages/astro/src/server/clerk-middleware.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index d96df4b4954..8ff486049be 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -243,6 +243,12 @@ Check if signInUrl is missing from your configuration or if it is not an absolut * doesn't serve a cached response during the authentication flow. */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { + // Only run on Netlify environment + // eslint-disable-next-line turbo/no-undeclared-env-vars + if (!process.env.NETLIFY) { + return; + } + const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); // If location header is the original URL before the handshake redirects, add cache bust param if (!hasHandshakeQueryParam) { From 098827752eff41037ff7381cb945344d3f279340 Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Mon, 9 Dec 2024 19:50:50 -0800 Subject: [PATCH 08/11] chore(astro): add changeset --- .changeset/hungry-fishes-invent.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hungry-fishes-invent.md diff --git a/.changeset/hungry-fishes-invent.md b/.changeset/hungry-fishes-invent.md new file mode 100644 index 00000000000..e8c1b421aa5 --- /dev/null +++ b/.changeset/hungry-fishes-invent.md @@ -0,0 +1,5 @@ +--- +"@clerk/astro": patch +--- + +Fix handshake redirect loop with Netlify adapter From 31d36215dcb2c7369fc949a6126f917ad5eb6f6f Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Tue, 10 Dec 2024 09:12:50 -0800 Subject: [PATCH 09/11] chore(astro): Run netlify checker on dev instance only --- packages/astro/src/server/clerk-middleware.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index 8ff486049be..f3481e11bde 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -1,7 +1,7 @@ import type { AuthObject, ClerkClient } from '@clerk/backend'; import type { AuthenticateRequestOptions, ClerkRequest, RedirectFun, RequestState } from '@clerk/backend/internal'; import { AuthStatus, constants, createClerkRequest, createRedirect } from '@clerk/backend/internal'; -import { isDevelopmentFromSecretKey } from '@clerk/shared/keys'; +import { isDevelopmentFromPublishableKey, isDevelopmentFromSecretKey } from '@clerk/shared/keys'; import { isHttpOrHttps } from '@clerk/shared/proxy'; import { eventMethodCalled } from '@clerk/shared/telemetry'; import { handleValueOrFn } from '@clerk/shared/utils'; @@ -243,9 +243,9 @@ Check if signInUrl is missing from your configuration or if it is not an absolut * doesn't serve a cached response during the authentication flow. */ function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { - // Only run on Netlify environment + // Only run on Netlify environment and Clerk development instance // eslint-disable-next-line turbo/no-undeclared-env-vars - if (!process.env.NETLIFY) { + if (!process.env.NETLIFY || !isDevelopmentFromPublishableKey(requestState.publishableKey)) { return; } From 6b05022e66514025365169ea327c3c370af9b5fe Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Tue, 10 Dec 2024 11:25:38 -0800 Subject: [PATCH 10/11] chore(astro): Use import meta when checking netlify build --- packages/astro/src/server/clerk-middleware.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index f3481e11bde..f56a0e7c6ba 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -245,16 +245,14 @@ Check if signInUrl is missing from your configuration or if it is not an absolut function handleNetlifyCacheInDevInstance(locationHeader: string, requestState: RequestState) { // Only run on Netlify environment and Clerk development instance // eslint-disable-next-line turbo/no-undeclared-env-vars - if (!process.env.NETLIFY || !isDevelopmentFromPublishableKey(requestState.publishableKey)) { - return; - } - - const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); - // If location header is the original URL before the handshake redirects, add cache bust param - if (!hasHandshakeQueryParam) { - const url = new URL(locationHeader); - url.searchParams.append(NETLIFY_CACHE_BUST_PARAM, Date.now().toString()); - requestState.headers.set('Location', url.toString()); + if (import.meta.env.NETLIFY && isDevelopmentFromPublishableKey(requestState.publishableKey)) { + const hasHandshakeQueryParam = locationHeader.includes('__clerk_handshake'); + // If location header is the original URL before the handshake redirects, add cache bust param + if (!hasHandshakeQueryParam) { + const url = new URL(locationHeader); + url.searchParams.append(NETLIFY_CACHE_BUST_PARAM, Date.now().toString()); + requestState.headers.set('Location', url.toString()); + } } } From 4e352f9077ea83b602d432eff38aea7d57d9c85b Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Tue, 10 Dec 2024 13:55:55 -0800 Subject: [PATCH 11/11] chore(astro): Update changeset text --- .changeset/hungry-fishes-invent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/hungry-fishes-invent.md b/.changeset/hungry-fishes-invent.md index e8c1b421aa5..523dab125bb 100644 --- a/.changeset/hungry-fishes-invent.md +++ b/.changeset/hungry-fishes-invent.md @@ -2,4 +2,4 @@ "@clerk/astro": patch --- -Fix handshake redirect loop with Netlify adapter +Fix handshake redirect loop in Netlify deployments