@@ -13,11 +13,128 @@ type OrganizationDrawerProps = {
1313 isRepresentative : boolean
1414}
1515
16- export const doLogout = ( ) => {
16+ const clearBrowserStorageForCurrentDomain = async ( ) => {
17+ if ( typeof window === 'undefined' || ! storeConfig ) return
18+
19+ // Clear Faststore-specific sessionStorage keys
20+ try {
21+ const sessionStorageKeys = [
22+ 'faststore_session_ready' ,
23+ 'faststore_auth_cookie_value' ,
24+ 'faststore_cache_bust_last_value' ,
25+ ]
26+
27+ for ( const key of sessionStorageKeys ) {
28+ try {
29+ window . sessionStorage ?. removeItem ( key )
30+ } catch { }
31+ }
32+
33+ // Remove all keys starting with __fs_gallery_page_ (used for PLP pagination)
34+ try {
35+ const keysToRemove : string [ ] = [ ]
36+ for ( let i = 0 ; i < window . sessionStorage . length ; i ++ ) {
37+ const key = window . sessionStorage . key ( i )
38+ if ( key && key . startsWith ( '__fs_gallery_page_' ) ) {
39+ keysToRemove . push ( key )
40+ }
41+ }
42+ for ( const key of keysToRemove ) {
43+ try {
44+ window . sessionStorage . removeItem ( key )
45+ } catch { }
46+ }
47+ } catch { }
48+ } catch { }
49+
50+ // Clear all cookies containing 'vtex' in the name (case-insensitive)
51+ try {
52+ const hostname = window . location . hostname
53+ const secure = window . location . protocol === 'https:'
54+
55+ // Extract all cookie names from document.cookie
56+ const allCookieNames = document . cookie
57+ . split ( ';' )
58+ . map ( ( c ) => c . trim ( ) )
59+ . filter ( Boolean )
60+ . map ( ( c ) => c . split ( '=' ) [ 0 ] )
61+ . filter ( Boolean )
62+
63+ // Filter cookies that contain 'vtex' (case-insensitive)
64+ const vtexCookieNames = allCookieNames . filter ( ( name ) =>
65+ name . toLowerCase ( ) . includes ( 'vtex' )
66+ )
67+
68+ const pathname = window . location . pathname || '/'
69+ const pathParts = pathname . split ( '/' ) . filter ( Boolean )
70+ const paths : string [ ] = [ '/' ]
71+
72+ let current = ''
73+ for ( const part of pathParts ) {
74+ current += `/${ part } `
75+ if ( ! paths . includes ( current ) ) paths . push ( current )
76+ }
77+
78+ const domains : Array < string | undefined > = [
79+ undefined , // host-only cookie
80+ hostname ,
81+ hostname . startsWith ( '.' ) ? hostname : `.${ hostname } ` ,
82+ ]
83+
84+ const expire = ( name : string , path : string , domain ?: string ) => {
85+ const domainAttr = domain ? `; domain=${ domain } ` : ''
86+ const secureAttr = secure ? '; secure' : ''
87+ document . cookie = `${ name } =; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; path=${ path } ${ domainAttr } ; samesite=lax${ secureAttr } `
88+ }
89+
90+ for ( const name of vtexCookieNames ) {
91+ for ( const path of paths ) {
92+ for ( const domain of domains ) {
93+ try {
94+ expire ( name , path , domain )
95+ } catch { }
96+ }
97+ }
98+ }
99+ } catch { }
100+
101+ // Clear IndexedDB (keyval-store)
102+ try {
103+ if ( ! ( 'indexedDB' in window ) ) return
104+
105+ const idb = window . indexedDB
106+ if ( ! idb ) return
107+
108+ await new Promise < void > ( ( resolve ) => {
109+ const req = idb . deleteDatabase ( 'keyval-store' )
110+ req . onsuccess = ( ) => resolve ( )
111+ req . onerror = ( ) => resolve ( )
112+ req . onblocked = ( ) => resolve ( )
113+ } )
114+ } catch { }
115+ }
116+
117+ export const doLogout = async ( _event ?: unknown ) => {
17118 if ( ! storeConfig ) return
18- window . location . assign (
19- `${ storeConfig . secureSubdomain } /api/vtexid/pub/logout?scope=${ storeConfig . api . storeId } &returnUrl=${ storeConfig . storeUrl } `
20- )
119+
120+ try {
121+ // Clear HttpOnly cookies via API endpoint (server-side)
122+ try {
123+ await fetch ( '/api/logout' , {
124+ method : 'POST' ,
125+ credentials : 'include' ,
126+ } )
127+ } catch {
128+ // Continue even if API call fails
129+ }
130+
131+ // Clear client-side storage (sessionStorage, localStorage, IndexedDB, non-HttpOnly cookies)
132+ await clearBrowserStorageForCurrentDomain ( )
133+ } finally {
134+ window . location . assign (
135+ `${ storeConfig . secureSubdomain } /api/vtexid/pub/logout?scope=${ storeConfig . api . storeId } &returnUrl=${ storeConfig . storeUrl } `
136+ )
137+ }
21138}
22139
23140export const OrganizationDrawer = ( {
0 commit comments