Skip to content

Commit 84867be

Browse files
authored
fix(backend): Satellite domains dev sync (#4864)
1 parent 04276fe commit 84867be

File tree

3 files changed

+75
-10
lines changed

3 files changed

+75
-10
lines changed

.changeset/grumpy-foxes-sneeze.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/backend': patch
3+
---
4+
5+
Fixes an issue with the satellite sync flow for development instances.

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

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ expect.extend({
7171
};
7272
} else {
7373
return {
74-
message: () => `expected to be signed out`,
74+
message: () => `expected to be signed out, but got ${received.status}`,
7575
pass: false,
7676
};
7777
}
@@ -190,7 +190,7 @@ expect.extend({
190190
};
191191
} else {
192192
return {
193-
message: () => `expected to be signed in`,
193+
message: () => `expected to be signed in, but got ${received.status}`,
194194
pass: false,
195195
};
196196
}
@@ -603,6 +603,42 @@ describe('tokens.authenticateRequest(options)', () => {
603603
expect(requestState.toAuth()).toBeNull();
604604
});
605605

606+
test('cookieToken: redirects to signInUrl when is satellite dev and not synced', async () => {
607+
server.use(
608+
http.get('https://api.clerk.test/v1/jwks', () => {
609+
return HttpResponse.json(mockJwks);
610+
}),
611+
);
612+
613+
const requestState = await authenticateRequest(
614+
mockRequestWithCookies(
615+
{},
616+
{
617+
__client_uat: '0',
618+
},
619+
),
620+
mockOptions({
621+
secretKey: 'deadbeef',
622+
publishableKey: PK_TEST,
623+
clientUat: '0',
624+
isSatellite: true,
625+
signInUrl: 'https://primary.dev/sign-in',
626+
domain: 'satellite.dev',
627+
}),
628+
);
629+
630+
expect(requestState).toMatchHandshake({
631+
reason: AuthErrorReason.SatelliteCookieNeedsSyncing,
632+
isSatellite: true,
633+
signInUrl: 'https://primary.dev/sign-in',
634+
domain: 'satellite.dev',
635+
});
636+
expect(requestState.message).toBe('');
637+
expect(requestState.headers.get('location')).toEqual(
638+
`https://primary.dev/sign-in?__clerk_redirect_url=http%3A%2F%2Fexample.com%2Fpath`,
639+
);
640+
});
641+
606642
test('cookieToken: returns signed out is satellite but a non-browser request [11y]', async () => {
607643
const requestState = await authenticateRequest(
608644
mockRequestWithCookies(
@@ -652,6 +688,32 @@ describe('tokens.authenticateRequest(options)', () => {
652688
expect(requestState.toAuth()).toBeNull();
653689
});
654690

691+
test('cookieToken: does not trigger satellite sync if just synced', async () => {
692+
const requestState = await authenticateRequest(
693+
mockRequestWithCookies(
694+
{},
695+
{
696+
__clerk_db_jwt: mockJwt,
697+
},
698+
`http://satellite.example/path?__clerk_synced=true`,
699+
),
700+
mockOptions({
701+
secretKey: 'sk_test_deadbeef',
702+
signInUrl: 'http://primary.example/sign-in',
703+
isSatellite: true,
704+
domain: 'satellite.example',
705+
}),
706+
);
707+
708+
expect(requestState).toBeSignedOut({
709+
reason: AuthErrorReason.SessionTokenAndUATMissing,
710+
isSatellite: true,
711+
domain: 'satellite.example',
712+
signInUrl: 'http://primary.example/sign-in',
713+
});
714+
expect(requestState.toAuth()).toBeSignedOutToAuth();
715+
});
716+
655717
test('cookieToken: returns handshake when app is not satellite and responds to syncing on dev instances[12y]', async () => {
656718
const sp = new URLSearchParams();
657719
sp.set('__clerk_redirect_url', 'http://localhost:3000');

packages/backend/src/tokens/request.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,11 @@ ${error.getFullMessage()}`,
521521
}
522522

523523
// Multi-domain development sync flow
524-
if (authenticateContext.instanceType === 'development' && isRequestEligibleForMultiDomainSync) {
524+
if (
525+
authenticateContext.instanceType === 'development' &&
526+
isRequestEligibleForMultiDomainSync &&
527+
!authenticateContext.clerkUrl.searchParams.has(constants.QueryParameters.ClerkSynced)
528+
) {
525529
// initiate MD sync
526530

527531
// signInUrl exists, checked at the top of `authenticateRequest`
@@ -530,10 +534,6 @@ ${error.getFullMessage()}`,
530534
constants.QueryParameters.ClerkRedirectUrl,
531535
authenticateContext.clerkUrl.toString(),
532536
);
533-
redirectURL.searchParams.append(
534-
constants.QueryParameters.HandshakeReason,
535-
AuthErrorReason.SatelliteCookieNeedsSyncing,
536-
);
537537
const headers = new Headers({ [constants.Headers.Location]: redirectURL.toString() });
538538
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.SatelliteCookieNeedsSyncing, '', headers);
539539
}
@@ -554,11 +554,9 @@ ${error.getFullMessage()}`,
554554
);
555555
}
556556
redirectBackToSatelliteUrl.searchParams.append(constants.QueryParameters.ClerkSynced, 'true');
557-
const authErrReason = AuthErrorReason.PrimaryRespondsToSyncing;
558-
redirectBackToSatelliteUrl.searchParams.append(constants.QueryParameters.HandshakeReason, authErrReason);
559557

560558
const headers = new Headers({ [constants.Headers.Location]: redirectBackToSatelliteUrl.toString() });
561-
return handleMaybeHandshakeStatus(authenticateContext, authErrReason, '', headers);
559+
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.PrimaryRespondsToSyncing, '', headers);
562560
}
563561
/**
564562
* End multi-domain sync flows

0 commit comments

Comments
 (0)