Skip to content

Commit 2df6b35

Browse files
committed
Revert "feat(*): auto-proxy for eligible hosts (#8035)"
This reverts commit 9b57986.
1 parent 61e0a78 commit 2df6b35

14 files changed

Lines changed: 15 additions & 580 deletions

File tree

packages/backend/src/tokens/__tests__/authenticateContext.test.ts

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -258,71 +258,6 @@ describe('AuthenticateContext', () => {
258258
});
259259
});
260260

261-
describe('auto-proxy for eligible hosts', () => {
262-
const originalEnv = process.env;
263-
264-
beforeEach(() => {
265-
process.env = {
266-
...originalEnv,
267-
VERCEL_TARGET_ENV: 'production',
268-
VERCEL_PROJECT_PRODUCTION_URL: 'myapp-abc123.vercel.app',
269-
};
270-
});
271-
272-
afterEach(() => {
273-
process.env = originalEnv;
274-
});
275-
276-
it('auto-derives proxyUrl when Vercel env vars indicate production vercel.app', async () => {
277-
const clerkRequest = createClerkRequest(new Request('https://myapp-abc123.vercel.app/dashboard'));
278-
const context = await createAuthenticateContext(clerkRequest, {
279-
publishableKey: pkLive,
280-
});
281-
282-
expect(context.proxyUrl).toBe('https://myapp-abc123.vercel.app/__clerk');
283-
});
284-
285-
it('does NOT auto-derive proxyUrl for development keys', async () => {
286-
const clerkRequest = createClerkRequest(new Request('https://myapp-abc123.vercel.app/dashboard'));
287-
const context = await createAuthenticateContext(clerkRequest, {
288-
publishableKey: pkTest,
289-
});
290-
291-
expect(context.proxyUrl).toBeUndefined();
292-
});
293-
294-
it('does NOT auto-derive proxyUrl when Vercel env vars are absent', async () => {
295-
delete process.env.VERCEL_TARGET_ENV;
296-
delete process.env.VERCEL_PROJECT_PRODUCTION_URL;
297-
const clerkRequest = createClerkRequest(new Request('https://myapp-abc123.vercel.app/dashboard'));
298-
const context = await createAuthenticateContext(clerkRequest, {
299-
publishableKey: pkLive,
300-
});
301-
302-
expect(context.proxyUrl).toBeUndefined();
303-
});
304-
305-
it('explicit proxyUrl takes precedence over auto-detection', async () => {
306-
const clerkRequest = createClerkRequest(new Request('https://myapp-abc123.vercel.app/dashboard'));
307-
const context = await createAuthenticateContext(clerkRequest, {
308-
publishableKey: pkLive,
309-
proxyUrl: 'https://custom-proxy.example.com/__clerk',
310-
});
311-
312-
expect(context.proxyUrl).toBe('https://custom-proxy.example.com/__clerk');
313-
});
314-
315-
it('explicit domain skips auto-detection', async () => {
316-
const clerkRequest = createClerkRequest(new Request('https://myapp-abc123.vercel.app/dashboard'));
317-
const context = await createAuthenticateContext(clerkRequest, {
318-
publishableKey: pkLive,
319-
domain: 'clerk.myapp.com',
320-
});
321-
322-
expect(context.proxyUrl).toBeUndefined();
323-
});
324-
});
325-
326261
// Added these tests to verify that the generated sha-1 is the same as the one used in cookie assignment
327262
// Tests copied from packages/shared/src/__tests__/keys.test.ts
328263
describe('getCookieSuffix(publishableKey, subtle)', () => {

packages/backend/src/tokens/authenticateContext.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { buildAccountsBaseUrl } from '@clerk/shared/buildAccountsBaseUrl';
2-
import { getAutoProxyUrlFromEnvironment } from '@clerk/shared/proxy';
32
import type { Jwt } from '@clerk/shared/types';
43
import { isCurrentDevAccountPortalOrigin, isLegacyDevAccountPortalOrigin } from '@clerk/shared/url';
54

@@ -71,18 +70,6 @@ class AuthenticateContext implements AuthenticateContext {
7170
private clerkRequest: ClerkRequest,
7271
options: AuthenticateRequestOptions,
7372
) {
74-
// Auto-detect proxy for supported platform deployments using environment
75-
// variables (e.g. VERCEL_TARGET_ENV, VERCEL_PROJECT_PRODUCTION_URL) instead
76-
// of request headers, which avoids X-Forwarded-Host spoofing concerns.
77-
const autoProxyPath = getAutoProxyUrlFromEnvironment({
78-
publishableKey: options.publishableKey ?? '',
79-
hasProxyUrl: !!options.proxyUrl,
80-
hasDomain: !!options.domain,
81-
});
82-
if (autoProxyPath) {
83-
options = { ...options, proxyUrl: `${clerkRequest.clerkUrl.origin}${autoProxyPath}` };
84-
}
85-
8673
if (options.acceptsToken === TokenType.M2MToken || options.acceptsToken === TokenType.ApiKey) {
8774
// For non-session tokens, we only want to set the header values.
8875
this.initHeaderValues();

packages/clerk-js/src/core/__tests__/clerk.test.ts

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,86 +2516,6 @@ describe('Clerk singleton', () => {
25162516
});
25172517
});
25182518
});
2519-
2520-
describe('auto-detection for eligible hosts', () => {
2521-
const originalLocation = window.location;
2522-
2523-
afterEach(() => {
2524-
Object.defineProperty(window, 'location', {
2525-
value: originalLocation,
2526-
writable: true,
2527-
});
2528-
});
2529-
2530-
test('auto-derives proxyUrl for production instances on eligible hosts', () => {
2531-
Object.defineProperty(window, 'location', {
2532-
value: {
2533-
...originalLocation,
2534-
hostname: 'myapp-abc123.vercel.app',
2535-
origin: 'https://myapp-abc123.vercel.app',
2536-
href: 'https://myapp-abc123.vercel.app/dashboard',
2537-
},
2538-
writable: true,
2539-
});
2540-
2541-
const sut = new Clerk(productionPublishableKey);
2542-
expect(sut.proxyUrl).toBe('https://myapp-abc123.vercel.app/__clerk');
2543-
});
2544-
2545-
test('does NOT auto-derive proxyUrl for development instances on eligible hosts', () => {
2546-
Object.defineProperty(window, 'location', {
2547-
value: {
2548-
...originalLocation,
2549-
hostname: 'myapp-abc123.vercel.app',
2550-
origin: 'https://myapp-abc123.vercel.app',
2551-
href: 'https://myapp-abc123.vercel.app/dashboard',
2552-
},
2553-
writable: true,
2554-
});
2555-
2556-
const sut = new Clerk(developmentPublishableKey);
2557-
expect(sut.proxyUrl).toBe('');
2558-
});
2559-
2560-
test('does NOT auto-derive proxyUrl for ineligible domains', () => {
2561-
const sut = new Clerk(productionPublishableKey);
2562-
expect(sut.proxyUrl).toBe('');
2563-
});
2564-
2565-
test('explicit proxyUrl takes precedence over auto-detection', () => {
2566-
Object.defineProperty(window, 'location', {
2567-
value: {
2568-
...originalLocation,
2569-
hostname: 'myapp-abc123.vercel.app',
2570-
origin: 'https://myapp-abc123.vercel.app',
2571-
href: 'https://myapp-abc123.vercel.app/dashboard',
2572-
},
2573-
writable: true,
2574-
});
2575-
2576-
const sut = new Clerk(productionPublishableKey, {
2577-
proxyUrl: 'https://custom-proxy.example.com/__clerk',
2578-
});
2579-
expect(sut.proxyUrl).toBe('https://custom-proxy.example.com/__clerk');
2580-
});
2581-
2582-
test('explicit domain skips auto-detection', () => {
2583-
Object.defineProperty(window, 'location', {
2584-
value: {
2585-
...originalLocation,
2586-
hostname: 'myapp-abc123.vercel.app',
2587-
origin: 'https://myapp-abc123.vercel.app',
2588-
href: 'https://myapp-abc123.vercel.app/dashboard',
2589-
},
2590-
writable: true,
2591-
});
2592-
2593-
const sut = new Clerk(productionPublishableKey, {
2594-
domain: 'clerk.myapp.com',
2595-
});
2596-
expect(sut.proxyUrl).toBe('');
2597-
});
2598-
});
25992519
});
26002520

26012521
describe('buildUrlWithAuth', () => {

packages/clerk-js/src/core/clerk.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,7 @@ import { windowNavigate } from '@clerk/shared/internal/clerk-js/windowNavigate';
3838
import { parsePublishableKey } from '@clerk/shared/keys';
3939
import { logger } from '@clerk/shared/logger';
4040
import { CLERK_NETLIFY_CACHE_BUST_PARAM } from '@clerk/shared/netlifyCacheHandler';
41-
import {
42-
AUTO_PROXY_PATH,
43-
isHttpOrHttps,
44-
isValidProxyUrl,
45-
proxyUrlToAbsoluteURL,
46-
shouldAutoProxy,
47-
} from '@clerk/shared/proxy';
41+
import { isHttpOrHttps, isValidProxyUrl, proxyUrlToAbsoluteURL } from '@clerk/shared/proxy';
4842
import {
4943
eventPrebuiltComponentMounted,
5044
eventPrebuiltComponentOpened,
@@ -367,14 +361,7 @@ export class Clerk implements ClerkInterface {
367361
if (!isValidProxyUrl(_unfilteredProxy)) {
368362
errorThrower.throwInvalidProxyUrl({ url: _unfilteredProxy });
369363
}
370-
const resolved = proxyUrlToAbsoluteURL(_unfilteredProxy);
371-
if (resolved) {
372-
return resolved;
373-
}
374-
// Auto-detect when no explicit proxy or domain is configured (production only)
375-
if (!this.#domain && this.#instanceType === 'production' && shouldAutoProxy(window.location.hostname)) {
376-
return `${window.location.origin}${AUTO_PROXY_PATH}`;
377-
}
364+
return proxyUrlToAbsoluteURL(_unfilteredProxy);
378365
}
379366

380367
if (typeof this.#proxyUrl === 'function') {

packages/nextjs/src/app-router/server/__tests__/DynamicClerkScripts.test.tsx

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,4 @@ describe('DynamicClerkScripts', () => {
8686
expect(html).not.toContain('nonce="test');
8787
expect(html).not.toContain('nonce="csp');
8888
});
89-
90-
it('renders initial script tags with relative proxied asset URLs', async () => {
91-
mockHeaders.mockResolvedValue(
92-
new Map([
93-
['X-Nonce', null],
94-
['Content-Security-Policy', ''],
95-
]),
96-
);
97-
98-
const html = await render(
99-
DynamicClerkScripts({
100-
...defaultProps,
101-
proxyUrl: '/__clerk',
102-
}),
103-
);
104-
105-
expect(html).toContain('src="/__clerk/npm/@clerk/clerk-js@');
106-
expect(html).toContain('href="/__clerk/npm/@clerk/ui@');
107-
expect(html).toContain('data-clerk-proxy-url="/__clerk"');
108-
});
10989
});

packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,40 +1326,6 @@ describe('frontendApiProxy multi-domain support', () => {
13261326
});
13271327
});
13281328

1329-
describe('auto-proxy for eligible hosts', () => {
1330-
const productionPublishableKey = 'pk_live_Y2xlcmsuaW5jbHVkZWQua2F0eWRpZC05Mi5sY2wuZGV2JA';
1331-
1332-
it('auto-intercepts /__clerk/* requests on eligible hostnames', async () => {
1333-
const req = new NextRequest(new URL('/__clerk/v1/client', 'https://myapp-abc123.vercel.app').toString(), {
1334-
method: 'GET',
1335-
headers: new Headers(),
1336-
});
1337-
1338-
const resp = await clerkMiddleware({ publishableKey: productionPublishableKey })(req, {} as NextFetchEvent);
1339-
1340-
// Proxy should intercept the request — authenticateRequest should NOT be called
1341-
expect((await clerkClient()).authenticateRequest).not.toBeCalled();
1342-
expect(resp?.status).toBeDefined();
1343-
});
1344-
1345-
it('uses request.nextUrl for auto-detection', async () => {
1346-
const req = new NextRequest('http://127.0.0.1:3000/__clerk/v1/client', {
1347-
method: 'GET',
1348-
headers: new Headers(),
1349-
});
1350-
1351-
Object.defineProperty(req, 'nextUrl', {
1352-
value: new URL('https://myapp-abc123.vercel.app/__clerk/v1/client'),
1353-
configurable: true,
1354-
});
1355-
1356-
const resp = await clerkMiddleware({ publishableKey: productionPublishableKey })(req, {} as NextFetchEvent);
1357-
1358-
expect((await clerkClient()).authenticateRequest).not.toBeCalled();
1359-
expect(resp?.status).toBeDefined();
1360-
});
1361-
});
1362-
13631329
describe('contentSecurityPolicy option', () => {
13641330
it('forwards CSP headers as request headers when strict mode is enabled', async () => {
13651331
const resp = await clerkMiddleware({

packages/nextjs/src/server/clerkMiddleware.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ import {
2121
TokenType,
2222
} from '@clerk/backend/internal';
2323
import { clerkFrontendApiProxy, DEFAULT_PROXY_PATH, matchProxyPath } from '@clerk/backend/proxy';
24-
import { isProductionFromPublishableKey, parsePublishableKey } from '@clerk/shared/keys';
24+
import { parsePublishableKey } from '@clerk/shared/keys';
2525
import { handleNetlifyCacheInDevInstance } from '@clerk/shared/netlifyCacheHandler';
2626
import { isMalformedURLError } from '@clerk/shared/pathMatcher';
27-
import { shouldAutoProxy } from '@clerk/shared/proxy';
2827
import { notFound as nextjsNotFound } from 'next/navigation';
2928
import type { NextMiddleware, NextRequest } from 'next/server';
3029
import { NextResponse } from 'next/server';
@@ -36,7 +35,7 @@ import type { Logger, LoggerNoCommit } from '../utils/debugLogger';
3635
import { withLogger } from '../utils/debugLogger';
3736
import { canUseKeyless } from '../utils/feature-flags';
3837
import { clerkClient } from './clerkClient';
39-
import { DOMAIN, PROXY_URL, PUBLISHABLE_KEY, SECRET_KEY, SIGN_IN_URL, SIGN_UP_URL } from './constants';
38+
import { PUBLISHABLE_KEY, SECRET_KEY, SIGN_IN_URL, SIGN_UP_URL } from './constants';
4039
import { type ContentSecurityPolicyOptions, createContentSecurityPolicyHeaders } from './content-security-policy';
4140
import { errorThrower } from './errorThrower';
4241
import { getHeader } from './headers-utils';
@@ -162,20 +161,12 @@ export const clerkMiddleware = ((...args: unknown[]): NextMiddleware | NextMiddl
162161
);
163162

164163
// Handle Frontend API proxy requests early, before authentication
165-
const requestUrl = new URL(request.nextUrl.href);
166-
let frontendApiProxyConfig = resolvedParams.frontendApiProxy;
167-
168-
// Auto-detect when no explicit proxy or domain is configured
169-
const hasExplicitProxyOrDomain = resolvedParams.proxyUrl || PROXY_URL || resolvedParams.domain || DOMAIN;
170-
if (!frontendApiProxyConfig && !hasExplicitProxyOrDomain && isProductionFromPublishableKey(publishableKey)) {
171-
if (shouldAutoProxy(requestUrl.hostname)) {
172-
frontendApiProxyConfig = { enabled: true };
173-
}
174-
}
164+
const frontendApiProxyConfig = resolvedParams.frontendApiProxy;
175165
if (frontendApiProxyConfig) {
176166
const { enabled, path: proxyPath = DEFAULT_PROXY_PATH } = frontendApiProxyConfig;
177167

178168
// Resolve enabled - either boolean or function
169+
const requestUrl = new URL(request.url);
179170
const isEnabled = typeof enabled === 'function' ? enabled(requestUrl) : enabled;
180171

181172
if (isEnabled && matchProxyPath(request, { proxyPath })) {

0 commit comments

Comments
 (0)