From 09f905a8915a39179cbffb2149342ca138bedb77 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 10 Jul 2024 16:22:51 +0300 Subject: [PATCH] fix(clerk-js): Clear session after deleting an account (#3628) Co-authored-by: panteliselef --- .changeset/chatty-feet-battle.md | 5 ++ .../testUtils/userProfilePageObject.ts | 2 +- integration/tests/user-profile.test.ts | 47 +++++++++++++++++++ packages/clerk-js/src/core/clerk.ts | 5 +- .../components/UserProfile/DeleteUserForm.tsx | 14 +++--- 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 .changeset/chatty-feet-battle.md diff --git a/.changeset/chatty-feet-battle.md b/.changeset/chatty-feet-battle.md new file mode 100644 index 00000000000..f91696d5072 --- /dev/null +++ b/.changeset/chatty-feet-battle.md @@ -0,0 +1,5 @@ +--- +"@clerk/clerk-js": patch +--- + +Bug fix: Clear session cookie after a user deletes their account diff --git a/integration/testUtils/userProfilePageObject.ts b/integration/testUtils/userProfilePageObject.ts index 05ecb7f9195..bf8473ed4af 100644 --- a/integration/testUtils/userProfilePageObject.ts +++ b/integration/testUtils/userProfilePageObject.ts @@ -6,7 +6,7 @@ import { common } from './commonPageObject'; export type EnchancedPage = ReturnType; export type TestArgs = { page: EnchancedPage; context: BrowserContext; browser: Browser }; -export type Sections = 'profile' | 'emailAddresses' | 'username' | 'phoneNumbers'; +export type Sections = 'profile' | 'emailAddresses' | 'username' | 'phoneNumbers' | 'danger'; export const createUserProfileComponentPageObject = (testArgs: TestArgs) => { const { page } = testArgs; diff --git a/integration/tests/user-profile.test.ts b/integration/tests/user-profile.test.ts index 9f1cfbc685e..d79375879d2 100644 --- a/integration/tests/user-profile.test.ts +++ b/integration/tests/user-profile.test.ts @@ -264,4 +264,51 @@ export default function Page() { state: 'visible', }); }); + + test('can delete account', async ({ page, context }) => { + const m = createTestUtils({ app }); + const delFakeUser = m.services.users.createFakeUser({ + withUsername: true, + fictionalEmail: true, + withPhoneNumber: true, + }); + await m.services.users.createBapiUser({ + ...delFakeUser, + username: undefined, + phoneNumber: undefined, + }); + + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.waitForMounted(); + await u.po.signIn.signInWithEmailAndInstantPassword({ email: delFakeUser.email, password: delFakeUser.password }); + await u.po.expect.toBeSignedIn(); + + await u.po.userProfile.goTo(); + await u.po.userProfile.waitForMounted(); + await u.po.userProfile.switchToSecurityTab(); + + await u.page + .getByRole('button', { + name: /delete account/i, + }) + .click(); + + await u.page.locator('input[name=deleteConfirmation]').fill('Delete account'); + + await u.page + .getByRole('button', { + name: /delete account/i, + }) + .click(); + + await u.po.expect.toBeSignedOut(); + + await u.page.waitForAppUrl('/'); + + // Make sure that the session cookie is deleted + const sessionCookieList = (await u.page.context().cookies()).filter(cookie => cookie.name === '__session'); + + expect(sessionCookieList.length).toBe(0); + }); }); diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index cf047327ca0..5ba17d7ee3c 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -732,7 +732,10 @@ export class Clerk implements ClerkInterface { } // getToken syncs __session and __client_uat to cookies using events.TokenUpdate dispatched event. - await newSession?.getToken(); + const token = await newSession?.getToken(); + if (!token) { + eventBus.dispatch(events.TokenUpdate, { token: null }); + } //2. If there's a beforeEmit, typically we're navigating. Emit the session as // undefined, then wait for beforeEmit to complete before emitting the new session. diff --git a/packages/clerk-js/src/ui/components/UserProfile/DeleteUserForm.tsx b/packages/clerk-js/src/ui/components/UserProfile/DeleteUserForm.tsx index 37515f17f2f..d50246bc5e9 100644 --- a/packages/clerk-js/src/ui/components/UserProfile/DeleteUserForm.tsx +++ b/packages/clerk-js/src/ui/components/UserProfile/DeleteUserForm.tsx @@ -1,4 +1,4 @@ -import { useUser } from '@clerk/shared/react'; +import { useClerk, useUser } from '@clerk/shared/react'; import { useSignOutContext } from '../../contexts'; import { Col, localizationKeys, Text, useLocalizations } from '../../customizables'; @@ -15,6 +15,7 @@ export const DeleteUserForm = withCardStateProvider((props: DeleteUserFormProps) const { user } = useUser(); const { t } = useLocalizations(); const { otherSessions } = useMultipleSessions({ user }); + const { setActive } = useClerk(); const confirmationField = useFormControl('deleteConfirmation', '', { type: 'text', @@ -38,12 +39,13 @@ export const DeleteUserForm = withCardStateProvider((props: DeleteUserFormProps) } await user.delete(); - // TODO: Investigate if we need to call `setActive` with {session: null} - if (otherSessions.length === 0) { - return navigateAfterSignOut(); - } - await navigateAfterMultiSessionSingleSignOutUrl(); + const navigationCallback = + otherSessions.length === 0 ? navigateAfterSignOut : navigateAfterMultiSessionSingleSignOutUrl; + return await setActive({ + session: null, + beforeEmit: navigationCallback, + }); } catch (e) { handleError(e, [], card.setError); }