From 6819353a1956dbccbd876bb4deed5d8cd90a2d98 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Fri, 22 May 2026 18:03:55 -0400 Subject: [PATCH 1/2] Improve satellite redirect loop diagnostics --- .../src/tokens/__tests__/request.test.ts | 34 +++++++++++++++++++ packages/backend/src/tokens/request.ts | 9 ++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/tokens/__tests__/request.test.ts b/packages/backend/src/tokens/__tests__/request.test.ts index e9b5fa6bfda..f2ab2b5a663 100644 --- a/packages/backend/src/tokens/__tests__/request.test.ts +++ b/packages/backend/src/tokens/__tests__/request.test.ts @@ -954,6 +954,40 @@ describe('tokens.authenticateRequest(options)', () => { }); }); + test('cookieToken: logs satellite-domain guidance when satellite sync enters a redirect loop', async () => { + const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); + + const requestState = await authenticateRequest( + mockRequestWithCookies( + { ...defaultHeaders, 'sec-fetch-dest': 'document' }, + { + __client_uat: '0', + __clerk_redirect_count: '3', + }, + `http://satellite.example/path?__clerk_synced=false`, + ), + mockOptions({ + secretKey: 'deadbeef', + publishableKey: PK_LIVE, + signInUrl: 'https://primary.example/sign-in', + isSatellite: true, + domain: 'satellite.example', + }), + ); + + expect(requestState).toBeSignedOut({ + reason: AuthErrorReason.SatelliteCookieNeedsSyncing, + isSatellite: true, + domain: 'satellite.example', + signInUrl: 'https://primary.example/sign-in', + }); + expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Satellite-domain authentication')); + expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('configured primary or satellite domain')); + expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('preview deployments')); + + consoleSpy.mockRestore(); + }); + test('cookieToken: triggers handshake when satelliteAutoSync is not set but __clerk_synced=false is present - dev', async () => { const requestState = await authenticateRequest( mockRequestWithCookies( diff --git a/packages/backend/src/tokens/request.ts b/packages/backend/src/tokens/request.ts index 415f1e4e0b6..89dfc0e01ee 100644 --- a/packages/backend/src/tokens/request.ts +++ b/packages/backend/src/tokens/request.ts @@ -338,7 +338,7 @@ export const authenticateRequest: AuthenticateRequest = (async ( // proceed with triggering handshake. const isRedirectLoop = handshakeService.checkAndTrackRedirectLoop(handshakeHeaders); if (isRedirectLoop) { - const msg = `Clerk: Refreshing the session token resulted in an infinite redirect loop. This usually means that your Clerk instance keys do not match - make sure to copy the correct publishable and secret keys from the Clerk dashboard.`; + const msg = getHandshakeRedirectLoopMessage(reason); console.log(msg); return signedOut({ tokenType: TokenType.SessionToken, @@ -351,6 +351,13 @@ export const authenticateRequest: AuthenticateRequest = (async ( return handshake(authenticateContext, reason, message, handshakeHeaders); } + function getHandshakeRedirectLoopMessage(reason: string): string { + if (reason === AuthErrorReason.SatelliteCookieNeedsSyncing) { + return `Clerk: Satellite-domain authentication resulted in an infinite redirect loop. Check that this request is using a configured primary or satellite domain for the production instance. For preview deployments, use a development/staging Clerk instance or a supported configured preview-domain setup.`; + } + return `Clerk: Refreshing the session token resulted in an infinite redirect loop. This usually means that your Clerk instance keys do not match - make sure to copy the correct publishable and secret keys from the Clerk dashboard.`; + } + /** * Determines if a handshake must occur to resolve a mismatch between the organization as specified * by the URL (according to the options) and the actual active organization on the session. From b870ac39530bc494463e68ca580d264fa52ea6cc Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Tue, 26 May 2026 17:23:14 -0400 Subject: [PATCH 2/2] Add satellite diagnostics changeset --- .changeset/polite-satellites-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-satellites-wait.md diff --git a/.changeset/polite-satellites-wait.md b/.changeset/polite-satellites-wait.md new file mode 100644 index 00000000000..beb01e8b819 --- /dev/null +++ b/.changeset/polite-satellites-wait.md @@ -0,0 +1,5 @@ +--- +'@clerk/backend': patch +--- + +Improve satellite-domain redirect loop diagnostics.