Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@W-14686284@ Fix Preview 403 errors when opening storefront being previewed in a new tab #1629

Merged
merged 8 commits into from
Jan 12, 2024
5 changes: 2 additions & 3 deletions packages/commerce-sdk-react/src/auth/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ jest.mock('./storage', () => {
return {
...originalModule,
CookieStorage: originalModule.MemoryStorage,
LocalStorage: originalModule.MemoryStorage
LocalStorage: originalModule.MemoryStorage,
LocalAndCookieStorage: originalModule.MemoryStorage
}
})

Expand Down Expand Up @@ -67,8 +68,6 @@ describe('Auth', () => {
expect(auth.get('refresh_token_guest')).toBe(refreshToken)
expect(auth.get('access_token')).toBe(accessToken)
// @ts-expect-error private property
expect([...auth.stores['cookie'].map.keys()]).toEqual([`cc-nx-g_siteId`])
// @ts-expect-error private property
expect([...auth.stores['local'].map.keys()]).toEqual([`access_token_siteId`])
})
test('set registered refresh token will clear guest refresh token, vise versa', () => {
Expand Down
16 changes: 13 additions & 3 deletions packages/commerce-sdk-react/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ import {
} from 'commerce-sdk-isomorphic'
import {jwtDecode, JwtPayload} from 'jwt-decode'
import {ApiClientConfigParams, Prettify, RemoveStringIndex} from '../hooks/types'
import {BaseStorage, LocalStorage, CookieStorage, MemoryStorage, StorageType} from './storage'
import {
BaseStorage,
LocalStorage,
CookieStorage,
MemoryStorage,
StorageType,
LocalAndCookieStorage
} from './storage'
import {CustomerType} from '../hooks/useCustomerType'
import {onClient} from '../utils'

Expand Down Expand Up @@ -106,14 +113,14 @@ const DATA_MAP: AuthDataMap = {
key: 'token_type'
},
refresh_token_guest: {
storageType: 'cookie',
storageType: 'localandcookie',
key: 'cc-nx-g',
callback: (store) => {
store.delete('cc-nx')
}
},
refresh_token_registered: {
storageType: 'cookie',
storageType: 'localandcookie',
key: 'cc-nx',
callback: (store) => {
store.delete('cc-nx-g')
Expand Down Expand Up @@ -199,6 +206,9 @@ class Auth {
this.stores = {
cookie: onClient() ? new CookieStorage(options) : new MemoryStorage(options),
local: onClient() ? new LocalStorage(options) : new MemoryStorage(options),
localandcookie: onClient()
? new LocalAndCookieStorage(options)
: new MemoryStorage(options),
memory: new MemoryStorage(options)
}

Expand Down
3 changes: 2 additions & 1 deletion packages/commerce-sdk-react/src/auth/storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

export type StorageType = 'cookie' | 'local' | 'memory'
export type StorageType = 'cookie' | 'local' | 'localandcookie' | 'memory'
export * from './base'
export * from './cookie'
export * from './local'
export * from './localandcookie'
export * from './memory'
62 changes: 62 additions & 0 deletions packages/commerce-sdk-react/src/auth/storage/localandcookie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2023, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import {BaseStorage, BaseStorageOptions} from './base'
import {LocalStorage} from './local'
import {CookieStorage} from './cookie'
import Cookies from 'js-cookie'

/**
* This class provides a storage mechanism that sets and deletes values in both LocalStorage and CookieStorage.
* The get method returns the value from LocalStorage if present, otherwise, the value is fetched from CookieStorage.
* The main use case for this class is to store and get authentication tokens using LocalStorage to keep browser
* contexts separated, while also storing the values in CookieStorage to maintain compatibility with Hybrid projects.
*/
export class LocalAndCookieStorage extends BaseStorage {
localStorageInstance: LocalStorage
cookieStorageInstance: CookieStorage
constructor(options?: BaseStorageOptions) {
super(options)
this.localStorageInstance = new LocalStorage(options)
this.cookieStorageInstance = new CookieStorage(options)
}
set(key: string, value: string, options?: Cookies.CookieAttributes) {
const oldValue = this.get(key)
const suffixedKey = this.getSuffixedKey(key)

this.localStorageInstance.set(key, value)
this.cookieStorageInstance.set(key, value, options)

const event = new StorageEvent('storage', {
key: suffixedKey,
oldValue: oldValue,
newValue: value
})
window.dispatchEvent(event)
}

get(key: string) {
const localStorageValue = this.localStorageInstance.get(key)
const cookieStorageValue = this.cookieStorageInstance.get(key)

return localStorageValue || cookieStorageValue || ''
}
delete(key: string, options?: Cookies.CookieAttributes) {
const suffixedKey = this.getSuffixedKey(key)
const oldValue = this.get(suffixedKey)

this.localStorageInstance.delete(key)
this.cookieStorageInstance.delete(key, options)

const localStorageEvent = new StorageEvent('storage', {
key: suffixedKey,
oldValue: oldValue,
newValue: null
})
window.dispatchEvent(localStorageEvent)
}
}