From 5800a1f94a94ca8a5334195a70c5fb4d1516ef2c Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Tue, 3 Dec 2024 20:56:57 -0600 Subject: [PATCH] fix(clerk-js): No TokenUpdate side-effect on `new Session()` (#4555) --- .changeset/slow-cougars-burn.md | 5 +++ .../clerk-js/src/core/__tests__/clerk.test.ts | 14 ++++++- packages/clerk-js/src/core/clerk.ts | 7 +++- .../clerk-js/src/core/resources/Session.ts | 1 - .../core/resources/__tests__/Session.test.ts | 37 +------------------ .../__snapshots__/Session.test.ts.snap | 34 ----------------- 6 files changed, 23 insertions(+), 75 deletions(-) create mode 100644 .changeset/slow-cougars-burn.md diff --git a/.changeset/slow-cougars-burn.md b/.changeset/slow-cougars-burn.md new file mode 100644 index 0000000000..56e17b7cb8 --- /dev/null +++ b/.changeset/slow-cougars-burn.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Remove side-effect from `Session` resource initialization that triggered a session cookie update. This cookie update is now explicitly part of the `Clerk.load()` flow. diff --git a/packages/clerk-js/src/core/__tests__/clerk.test.ts b/packages/clerk-js/src/core/__tests__/clerk.test.ts index 63df480e13..5fb04189ea 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.test.ts @@ -461,6 +461,7 @@ describe('Clerk singleton', () => { status: 'active', user: {}, getToken: jest.fn(), + lastActiveToken: { getRawString: () => mockJwt }, }; afterEach(() => { @@ -489,6 +490,15 @@ describe('Clerk singleton', () => { }); }); + it('updates auth cookie on load from fetched session', async () => { + mockClientFetch.mockReturnValue(Promise.resolve({ activeSessions: [mockSession] })); + + const sut = new Clerk(productionPublishableKey); + await sut.load(); + + expect(document.cookie).toContain(mockJwt); + }); + it('updates auth cookie on token:update event', async () => { mockClientFetch.mockReturnValue(Promise.resolve({ activeSessions: [mockSession] })); @@ -497,11 +507,11 @@ describe('Clerk singleton', () => { const token = { jwt: {}, - getRawString: () => mockJwt, + getRawString: () => 'updated-jwt', } as TokenResource; eventBus.dispatch(events.TokenUpdate, { token }); - expect(document.cookie).toContain(mockJwt); + expect(document.cookie).toContain('updated-jwt'); }); }); diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index a6b1ecf461..b5e0b5b826 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1666,7 +1666,12 @@ export class Clerk implements ClerkInterface { if (this.session) { const session = this.#getSessionFromClient(this.session.id); + + // Note: this might set this.session to null this.#setAccessors(session); + + // A client response contains its associated sessions, along with a fresh token, so we dispatch a token update event. + eventBus.dispatch(events.TokenUpdate, { token: this.session?.lastActiveToken }); } this.#emit(); @@ -1865,8 +1870,6 @@ export class Clerk implements ClerkInterface { // set in updateClient this.updateEnvironment(environment); - this.#authService.setActiveOrganizationInStorage(); - if (await this.#redirectFAPIInitiatedFlow()) { return false; } diff --git a/packages/clerk-js/src/core/resources/Session.ts b/packages/clerk-js/src/core/resources/Session.ts index 2249189589..4309e1ce89 100644 --- a/packages/clerk-js/src/core/resources/Session.ts +++ b/packages/clerk-js/src/core/resources/Session.ts @@ -107,7 +107,6 @@ export class Session extends BaseResource implements SessionResource { tokenId: this.#getCacheId(), tokenResolver: Promise.resolve(token), }); - eventBus.dispatch(events.TokenUpdate, { token }); } }; diff --git a/packages/clerk-js/src/core/resources/__tests__/Session.test.ts b/packages/clerk-js/src/core/resources/__tests__/Session.test.ts index b625c82a09..4ae056d068 100644 --- a/packages/clerk-js/src/core/resources/__tests__/Session.test.ts +++ b/packages/clerk-js/src/core/resources/__tests__/Session.test.ts @@ -11,41 +11,6 @@ describe('Session', () => { SessionTokenCache.clear(); }); - describe('creating new session', () => { - let dispatchSpy; - - beforeEach(() => { - dispatchSpy = jest.spyOn(eventBus, 'dispatch'); - BaseResource.clerk = clerkMock() as any; - }); - - afterEach(() => { - dispatchSpy?.mockRestore(); - BaseResource.clerk = null as any; - // @ts-ignore - global.fetch?.mockClear(); - SessionTokenCache.clear(); - }); - - it('dispatches token:update event on initialization with lastActiveToken', () => { - new Session({ - status: 'active', - id: 'session_1', - - object: 'session', - user: createUser({}), - last_active_organization_id: 'activeOrganization', - last_active_token: { object: 'token', jwt: mockJwt }, - actor: null, - created_at: new Date().getTime(), - updated_at: new Date().getTime(), - } as SessionJSON); - - expect(dispatchSpy).toHaveBeenCalledTimes(1); - expect(dispatchSpy.mock.calls[0]).toMatchSnapshot(); - }); - }); - describe('getToken()', () => { let dispatchSpy; @@ -101,7 +66,7 @@ describe('Session', () => { expect(BaseResource.clerk.getFapiClient().request).not.toHaveBeenCalled(); expect(token).toEqual(mockJwt); - expect(dispatchSpy).toHaveBeenCalledTimes(3); + expect(dispatchSpy).toHaveBeenCalledTimes(2); }); it('dispatches token:update event on getToken with active organization', async () => { diff --git a/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Session.test.ts.snap b/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Session.test.ts.snap index 0b53b387d0..ce9e54c2f0 100644 --- a/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Session.test.ts.snap +++ b/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Session.test.ts.snap @@ -1,39 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Session creating new session dispatches token:update event on initialization with lastActiveToken 1`] = ` -[ - "token:update", - { - "token": Token { - "getRawString": [Function], - "jwt": { - "claims": { - "__raw": "eyJhbGciOiJSUzI1NiIsImtpZCI6Imluc18yR0lvUWhiVXB5MGhYN0IyY1ZrdVRNaW5Yb0QiLCJ0eXAiOiJKV1QifQ.eyJhenAiOiJodHRwczovL2FjY291bnRzLmluc3BpcmVkLnB1bWEtNzQubGNsLmRldiIsImV4cCI6MTY2NjY0ODMxMCwiaWF0IjoxNjY2NjQ4MjUwLCJpc3MiOiJodHRwczovL2NsZXJrLmluc3BpcmVkLnB1bWEtNzQubGNsLmRldiIsIm5iZiI6MTY2NjY0ODI0MCwic2lkIjoic2Vzc18yR2JEQjRlbk5kQ2E1dlMxenBDM1h6Zzl0SzkiLCJzdWIiOiJ1c2VyXzJHSXBYT0VwVnlKdzUxcmtabjlLbW5jNlN4ciJ9.n1Usc-DLDftqA0Xb-_2w8IGs4yjCmwc5RngwbSRvwevuZOIuRoeHmE2sgCdEvjfJEa7ewL6EVGVcM557TWPW--g_J1XQPwBy8tXfz7-S73CEuyRFiR97L2AHRdvRtvGtwR-o6l8aHaFxtlmfWbQXfg4kFJz2UGe9afmh3U9-f_4JOZ5fa3mI98UMy1-bo20vjXeWQ9aGrqaxHQxjnzzC-1Kpi5LdPvhQ16H0dPB8MHRTSM5TAuLKTpPV7wqixmbtcc2-0k6b9FKYZNqRVTaIyV-lifZloBvdzlfOF8nW1VVH_fx-iW5Q3hovHFcJIULHEC1kcAYTubbxzpgeVQepGg", - "azp": "https://accounts.inspired.puma-74.lcl.dev", - "exp": 1666648310, - "iat": 1666648250, - "iss": "https://clerk.inspired.puma-74.lcl.dev", - "nbf": 1666648240, - "sid": "sess_2GbDB4enNdCa5vS1zpC3Xzg9tK9", - "sub": "user_2GIpXOEpVyJw51rkZn9Kmnc6Sxr", - }, - "encoded": { - "header": "eyJhbGciOiJSUzI1NiIsImtpZCI6Imluc18yR0lvUWhiVXB5MGhYN0IyY1ZrdVRNaW5Yb0QiLCJ0eXAiOiJKV1QifQ", - "payload": "eyJhenAiOiJodHRwczovL2FjY291bnRzLmluc3BpcmVkLnB1bWEtNzQubGNsLmRldiIsImV4cCI6MTY2NjY0ODMxMCwiaWF0IjoxNjY2NjQ4MjUwLCJpc3MiOiJodHRwczovL2NsZXJrLmluc3BpcmVkLnB1bWEtNzQubGNsLmRldiIsIm5iZiI6MTY2NjY0ODI0MCwic2lkIjoic2Vzc18yR2JEQjRlbk5kQ2E1dlMxenBDM1h6Zzl0SzkiLCJzdWIiOiJ1c2VyXzJHSXBYT0VwVnlKdzUxcmtabjlLbW5jNlN4ciJ9", - "signature": "n1Usc-DLDftqA0Xb-_2w8IGs4yjCmwc5RngwbSRvwevuZOIuRoeHmE2sgCdEvjfJEa7ewL6EVGVcM557TWPW--g_J1XQPwBy8tXfz7-S73CEuyRFiR97L2AHRdvRtvGtwR-o6l8aHaFxtlmfWbQXfg4kFJz2UGe9afmh3U9-f_4JOZ5fa3mI98UMy1-bo20vjXeWQ9aGrqaxHQxjnzzC-1Kpi5LdPvhQ16H0dPB8MHRTSM5TAuLKTpPV7wqixmbtcc2-0k6b9FKYZNqRVTaIyV-lifZloBvdzlfOF8nW1VVH_fx-iW5Q3hovHFcJIULHEC1kcAYTubbxzpgeVQepGg", - }, - "header": { - "alg": "RS256", - "kid": "ins_2GIoQhbUpy0hX7B2cVkuTMinXoD", - "typ": "JWT", - }, - }, - "pathRoot": "tokens", - }, - }, -] -`; - exports[`Session getToken() dispatches token:update event on getToken with active organization 1`] = ` [ "token:update",