Skip to content

Commit 6bb480e

Browse files
authored
fix(backend): Use domain only for satellite apps (#5919)
1 parent 74d2b21 commit 6bb480e

File tree

6 files changed

+63
-8
lines changed

6 files changed

+63
-8
lines changed

.changeset/moody-clouds-smile.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/backend': patch
3+
'@clerk/shared': patch
4+
---
5+
6+
Use domain in AuthenticateRequest only for satellite domains

integration/tests/handshake.test.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ test.describe('Client handshake @generic', () => {
2525
});
2626
// Strip trailing slash
2727
const devBrowserCookie = '__clerk_db_jwt=needstobeset;';
28-
const devBrowserQuery = '&__clerk_db_jwt=needstobeset';
2928

3029
test.beforeAll('setup local Clerk API mock', async () => {
3130
const env = appConfigs.envs.withEmailCodes
@@ -367,7 +366,11 @@ test.describe('Client handshake @generic', () => {
367366
});
368367
expect(res.status).toBe(307);
369368
const locationUrl = new URL(res.headers.get('location'));
370-
expect(locationUrl.origin + locationUrl.pathname).toBe('https://clerk.example.com/v1/client/handshake');
369+
370+
// The domain is ignored for non-satellite requests
371+
expect(locationUrl.hostname).not.toBe('example.com');
372+
373+
expect(locationUrl.origin + locationUrl.pathname).toContain('/v1/client/handshake');
371374
expect(locationUrl.searchParams.get('redirect_url')).toBe(`${app.serverUrl}/`);
372375
expect(locationUrl.searchParams.get('__clerk_hs_reason')).toBe(
373376
'session-token-expired-refresh-non-eligible-no-refresh-cookie',
@@ -376,6 +379,30 @@ test.describe('Client handshake @generic', () => {
376379
expect(locationUrl.searchParams.get('suffixed_cookies')).toBe('false');
377380
});
378381

382+
test('domain - prod satellite - domain is used as the redirect url', async () => {
383+
const config = generateConfig({
384+
mode: 'live',
385+
});
386+
const { token, claims } = config.generateToken({ state: 'expired' });
387+
const clientUat = claims.iat;
388+
const res = await fetch(app.serverUrl + '/', {
389+
headers: new Headers({
390+
Cookie: `__client_uat=${clientUat}; __session=${token}`,
391+
'X-Publishable-Key': config.pk,
392+
'X-Secret-Key': config.sk,
393+
'X-Satellite': 'true',
394+
'X-Domain': 'example.com',
395+
'Sec-Fetch-Dest': 'document',
396+
}),
397+
redirect: 'manual',
398+
});
399+
expect(res.status).toBe(307);
400+
const locationUrl = new URL(res.headers.get('location'));
401+
402+
// The domain is used as the redirect url
403+
expect(locationUrl.origin + locationUrl.pathname).toBe('https://clerk.example.com/v1/client/handshake');
404+
});
405+
379406
test('missing session token, positive uat - dev', async () => {
380407
const config = generateConfig({
381408
mode: 'test',

packages/backend/src/tokens/authenticateContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class AuthenticateContext implements AuthenticateContext {
167167
fatal: true,
168168
proxyUrl: options.proxyUrl,
169169
domain: options.domain,
170+
isSatellite: options.isSatellite,
170171
});
171172
this.instanceType = pk.instanceType;
172173
this.frontendApi = pk.frontendApi;

packages/clerk-js/bundlewatch.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.js", "maxSize": "598KB" },
4-
{ "path": "./dist/clerk.browser.js", "maxSize": "68.5KB" },
3+
{ "path": "./dist/clerk.js", "maxSize": "598kB" },
4+
{ "path": "./dist/clerk.browser.js", "maxSize": "69KB" },
55
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "113KB" },
66
{ "path": "./dist/clerk.headless*.js", "maxSize": "52KB" },
77
{ "path": "./dist/ui-common*.js", "maxSize": "105.1KB" },

packages/shared/src/__tests__/keys.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,32 @@ describe('parsePublishableKey(key)', () => {
7171
});
7272
});
7373

74-
it('applies the domain if provided for production keys', () => {
75-
expect(parsePublishableKey('pk_live_Y2xlcmsuY2xlcmsuZGV2JA==', { domain: 'example.com' })).toEqual({
74+
it('applies the domain if provided for production keys and isSatellite is true', () => {
75+
expect(
76+
parsePublishableKey('pk_live_Y2xlcmsuY2xlcmsuZGV2JA==', { domain: 'example.com', isSatellite: true }),
77+
).toEqual({
7678
frontendApi: 'clerk.example.com',
7779
instanceType: 'production',
7880
});
7981
});
82+
83+
it('ignores domain for production keys when isSatellite is false', () => {
84+
expect(
85+
parsePublishableKey('pk_live_Y2xlcmsuY2xlcmsuZGV2JA==', { domain: 'example.com', isSatellite: false }),
86+
).toEqual({
87+
frontendApi: 'clerk.clerk.dev',
88+
instanceType: 'production',
89+
});
90+
});
91+
92+
it('ignores domain for development keys even when isSatellite is true', () => {
93+
expect(
94+
parsePublishableKey('pk_test_Y2xlcmsuY2xlcmsuZGV2JA==', { domain: 'example.com', isSatellite: true }),
95+
).toEqual({
96+
frontendApi: 'clerk.clerk.dev',
97+
instanceType: 'development',
98+
});
99+
});
80100
});
81101

82102
describe('isPublishableKey(key)', () => {

packages/shared/src/keys.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type ParsePublishableKeyOptions = {
88
fatal?: boolean;
99
domain?: string;
1010
proxyUrl?: string;
11+
isSatellite?: boolean;
1112
};
1213

1314
const PUBLISHABLE_KEY_LIVE_PREFIX = 'pk_live_';
@@ -34,7 +35,7 @@ export function parsePublishableKey(
3435
): PublishableKey | null;
3536
export function parsePublishableKey(
3637
key: string | undefined,
37-
options: { fatal?: boolean; domain?: string; proxyUrl?: string } = {},
38+
options: { fatal?: boolean; domain?: string; proxyUrl?: string; isSatellite?: boolean } = {},
3839
): PublishableKey | null {
3940
key = key || '';
4041

@@ -59,7 +60,7 @@ export function parsePublishableKey(
5960

6061
if (options.proxyUrl) {
6162
frontendApi = options.proxyUrl;
62-
} else if (instanceType !== 'development' && options.domain) {
63+
} else if (instanceType !== 'development' && options.domain && options.isSatellite) {
6364
frontendApi = `clerk.${options.domain}`;
6465
}
6566

0 commit comments

Comments
 (0)