From c5ee9e628d12e8c3a6268e6de801081aff4700ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Poizat?= Date: Wed, 21 Jan 2026 07:42:06 +0100 Subject: [PATCH] fix: Avoid to log in again with same account because of SSO cookie We log in using an In App Browser that stores an SSO cookie. Unfortunately, we do not have a lot of control for this In App Browser which means that when we log out from the app and log in again, we already reconnectec automatically to the same account because the SSO cookie stills exist. By opening the /logout page of Sign Up app, we ensure that the SSO cookie is cleared. We do the same for Twake Mail. --- .../utils/deeplinkHandler.spec.ts | 20 ++++++++++++++++++ .../authentication/utils/deeplinkHandler.ts | 21 +++++++++++++++++++ src/hooks/useAppBootstrap.js | 5 +++++ src/libs/intents/localMethods.ts | 12 +++++++++++ 4 files changed, 58 insertions(+) create mode 100644 src/app/domain/authentication/utils/deeplinkHandler.spec.ts create mode 100644 src/app/domain/authentication/utils/deeplinkHandler.ts diff --git a/src/app/domain/authentication/utils/deeplinkHandler.spec.ts b/src/app/domain/authentication/utils/deeplinkHandler.spec.ts new file mode 100644 index 000000000..a9a9b24fb --- /dev/null +++ b/src/app/domain/authentication/utils/deeplinkHandler.spec.ts @@ -0,0 +1,20 @@ +import { handleLogoutDeepLink } from '/app/domain/authentication/utils/deeplinkHandler' +import { closeInAppBrowser } from '/libs/intents/InAppBrowser' + +jest.mock('/libs/intents/InAppBrowser') + +describe('deeplinkHandler', () => { + describe('handleLogoutDeepLink', () => { + it('should handle AfterLogout deep links', () => { + handleLogoutDeepLink('cozy://afterlogout') + + expect(closeInAppBrowser).toHaveBeenCalled() + }) + + it('should handle AfterLogout universal links', () => { + handleLogoutDeepLink('https://links.mycozy.cloud/flagship/afterlogout') + + expect(closeInAppBrowser).toHaveBeenCalled() + }) + }) +}) diff --git a/src/app/domain/authentication/utils/deeplinkHandler.ts b/src/app/domain/authentication/utils/deeplinkHandler.ts new file mode 100644 index 000000000..ad6b383dc --- /dev/null +++ b/src/app/domain/authentication/utils/deeplinkHandler.ts @@ -0,0 +1,21 @@ +import strings from '/constants/strings.json' +import { closeInAppBrowser } from '/libs/intents/InAppBrowser' + +export const handleLogoutDeepLink = (url: string): boolean => { + if (isAfterLogoutDeepLink(url)) { + void closeInAppBrowser() + + return true + } + + return false +} + +const isAfterLogoutDeepLink = (url: string): boolean => { + const deepLinks = [ + `${strings.COZY_SCHEME}afterlogout`, + `${strings.UNIVERSAL_LINK_BASE}/afterlogout` + ] + + return deepLinks.includes(url.toLowerCase()) +} diff --git a/src/hooks/useAppBootstrap.js b/src/hooks/useAppBootstrap.js index b98fc7048..daccbdf2b 100644 --- a/src/hooks/useAppBootstrap.js +++ b/src/hooks/useAppBootstrap.js @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react' import { deconstructCozyWebLinkWithSlug } from 'cozy-client' import { handleLogsDeepLink } from '/app/domain/logger/deeplinkHandler' +import { handleLogoutDeepLink } from '/app/domain/authentication/utils/deeplinkHandler' import rnperformance from '/app/domain/performances/measure' import { SentryCustomTags, setSentryTag } from '/libs/monitoring/Sentry' import { manageIconCache } from '/libs/functions/iconTable' @@ -190,6 +191,10 @@ export const useAppBootstrap = client => { return } + if (handleLogoutDeepLink(url)) { + return + } + if (!client) { const action = parseOnboardLink(url) diff --git a/src/libs/intents/localMethods.ts b/src/libs/intents/localMethods.ts index 477e82940..cd4487aa1 100644 --- a/src/libs/intents/localMethods.ts +++ b/src/libs/intents/localMethods.ts @@ -10,6 +10,7 @@ import { PostMeMessageOptions } from 'cozy-intent' import Minilog from 'cozy-minilog' +import flag from 'cozy-flags' import * as RootNavigation from '/libs/RootNavigation' import { isIapAvailable } from '/app/domain/iap/services/availableOffers' @@ -64,12 +65,23 @@ export const asyncLogout = async (client?: CozyClient): Promise => { throw new Error('Logout should not be called with undefined client') } + const signupUrl = flag('signup.url') as string | undefined + await sendKonnectorsLogs(client) await clearClientCachedData(client) await client.logout() await deleteKeychain() await clearCookies() await clearCozyData() + + // Delete SSO cookie from In App Browser to avoid being reconnected to same account + // when logging in again + if (signupUrl) { + const logoutUrl = `${signupUrl}/logout?url=cozy://afterlogout` + + await showInAppBrowser({ url: logoutUrl }) + } + RootNavigation.reset(routes.welcome, { screen: 'welcome' }) return Promise.resolve(null) }