diff --git a/.github/integ-config/integ-all.yml b/.github/integ-config/integ-all.yml index 249c54a53fd..c7316c37c1f 100644 --- a/.github/integ-config/integ-all.yml +++ b/.github/integ-config/integ-all.yml @@ -609,20 +609,6 @@ tests: sample_name: [subdomains] spec: subdomains browser: [chrome] - - test_name: integ_next_custom_auth - desc: 'Sign-in with Custom Auth flow' - framework: next - category: auth - sample_name: [custom-auth] - spec: custom-auth - browser: *minimal_browser_list - - test_name: integ_next_auth_sign_in_with_sms_mfa - desc: 'Resumable sign in with SMS MFA flow' - framework: next - category: auth - sample_name: [mfa] - spec: sign-in-resumable-mfa - browser: [chrome] # DISABLED Angular/Vue tests: # TODO: delete tests or add custom ui logic to support them. diff --git a/packages/auth/__tests__/providers/cognito/signInResumable.test.ts b/packages/auth/__tests__/providers/cognito/signInResumable.test.ts deleted file mode 100644 index 92f2170a9c6..00000000000 --- a/packages/auth/__tests__/providers/cognito/signInResumable.test.ts +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -import { Amplify, syncSessionStorage } from '@aws-amplify/core'; - -import { - setActiveSignInState, - signInStore, -} from '../../../src/providers/cognito/utils/signInStore'; -import { cognitoUserPoolsTokenProvider } from '../../../src/providers/cognito/tokenProvider'; -import { - ChallengeName, - RespondToAuthChallengeCommandOutput, -} from '../../../src/foundation/factories/serviceClients/cognitoIdentityProvider/types'; -import * as signInHelpers from '../../../src/providers/cognito/utils/signInHelpers'; -import { signIn } from '../../../src/providers/cognito'; - -import { setUpGetConfig } from './testUtils/setUpGetConfig'; -import { authAPITestParams } from './testUtils/authApiTestParams'; - -const signInStoreImplementation = require('../../../src/providers/cognito/utils/signInStore'); - -jest.mock('@aws-amplify/core/internals/utils'); -jest.mock('../../../src/providers/cognito/apis/getCurrentUser'); -jest.mock('@aws-amplify/core', () => ({ - ...(jest.createMockFromModule('@aws-amplify/core') as object), - Amplify: { - getConfig: jest.fn(() => ({})), - ADD_OAUTH_LISTENER: jest.fn(() => ({})), - }, - syncSessionStorage: { - setItem: jest.fn((key, value) => { - window.sessionStorage.setItem(key, value); - }), - getItem: jest.fn((key: string) => { - return window.sessionStorage.getItem(key); - }), - removeItem: jest.fn((key: string) => { - window.sessionStorage.removeItem(key); - }), - }, -})); - -const signInStateKeys: Record = { - username: 'CognitoSignInState.username', - challengeName: 'CognitoSignInState.challengeName', - signInSession: 'CognitoSignInState.signInSession', - expiry: 'CognitoSignInState.expiry', -}; - -const user1: Record = { - username: 'joonchoi', - challengeName: 'CUSTOM_CHALLENGE', - signInSession: '888577-ltfgo-42d8-891d-666l858766g7', - expiry: '1234567', -}; - -const populateValidTestSyncStorage = () => { - syncSessionStorage.setItem(signInStateKeys.username, user1.username); - syncSessionStorage.setItem( - signInStateKeys.signInSession, - user1.signInSession, - ); - syncSessionStorage.setItem( - signInStateKeys.challengeName, - user1.challengeName, - ); - syncSessionStorage.setItem( - signInStateKeys.expiry, - (new Date().getTime() + 9999999).toString(), - ); - - signInStore.dispatch({ - type: 'SET_INITIAL_STATE', - }); -}; - -const populateInvalidTestSyncStorage = () => { - syncSessionStorage.setItem(signInStateKeys.username, user1.username); - syncSessionStorage.setItem( - signInStateKeys.signInSession, - user1.signInSession, - ); - syncSessionStorage.setItem( - signInStateKeys.challengeName, - user1.challengeName, - ); - syncSessionStorage.setItem( - signInStateKeys.expiry, - (new Date().getTime() - 99999).toString(), - ); - - signInStore.dispatch({ - type: 'SET_INITIAL_STATE', - }); -}; - -describe('signInStore', () => { - const authConfig = { - Cognito: { - userPoolClientId: '123456-abcde-42d8-891d-666l858766g7', - userPoolId: 'us-west-7_ampjc', - }, - }; - - const session = '1234234232'; - const challengeName = 'SMS_MFA'; - const { username } = authAPITestParams.user1; - const { password } = authAPITestParams.user1; - - beforeEach(() => { - cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); - }); - - beforeAll(() => { - setUpGetConfig(Amplify); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - afterAll(() => { - jest.restoreAllMocks(); - }); - - test('LocalSignInState is empty after initialization', async () => { - const localSignInState = signInStore.getState(); - - expect(localSignInState).toEqual({ - challengeName: undefined, - signInSession: undefined, - username: undefined, - }); - signInStore.dispatch({ type: 'RESET_STATE' }); - }); - - test('State is set after calling setActiveSignInState', async () => { - const persistSignInStateSpy = jest.spyOn( - signInStoreImplementation, - 'persistSignInState', - ); - setActiveSignInState(user1); - const localSignInState = signInStore.getState(); - - expect(localSignInState).toEqual(user1); - expect(persistSignInStateSpy).toHaveBeenCalledTimes(1); - expect(persistSignInStateSpy).toHaveBeenCalledWith(user1); - signInStore.dispatch({ type: 'RESET_STATE' }); - }); - - test('State is updated after calling SignIn', async () => { - const handleUserSRPAuthflowSpy = jest - .spyOn(signInHelpers, 'handleUserSRPAuthFlow') - .mockImplementationOnce( - async (): Promise => ({ - ChallengeName: challengeName, - Session: session, - $metadata: {}, - ChallengeParameters: { - CODE_DELIVERY_DELIVERY_MEDIUM: 'SMS', - CODE_DELIVERY_DESTINATION: '*******9878', - }, - }), - ); - - await signIn({ - username, - password, - }); - const newLocalSignInState = signInStore.getState(); - - expect(handleUserSRPAuthflowSpy).toHaveBeenCalledTimes(1); - expect(newLocalSignInState).toEqual({ - challengeName, - signInSession: session, - username, - signInDetails: { - loginId: username, - authFlowType: 'USER_SRP_AUTH', - }, - }); - handleUserSRPAuthflowSpy.mockClear(); - }); - - test('The stored sign-in state should be rehydrated if the sign-in session is still valid.', () => { - populateValidTestSyncStorage(); - - const localSignInState = signInStore.getState(); - - expect(localSignInState).toEqual({ - username: user1.username, - challengeName: user1.challengeName, - signInSession: user1.signInSession, - }); - signInStore.dispatch({ type: 'RESET_STATE' }); - }); - - test('sign-in store should return undefined state when the sign-in session is expired', async () => { - populateInvalidTestSyncStorage(); - - const localSignInState = signInStore.getState(); - - expect(localSignInState).toEqual({ - username: undefined, - challengeName: undefined, - signInSession: undefined, - }); - signInStore.dispatch({ type: 'RESET_STATE' }); - }); - - test('State SignInSession is updated after dispatching custom session value', () => { - const persistSignInStateSpy = jest.spyOn( - signInStoreImplementation, - 'persistSignInState', - ); - const newSignInSessionID = '135790-dodge-2468-9aaa-kersh23lad00'; - - populateValidTestSyncStorage(); - - const localSignInState = signInStore.getState(); - expect(localSignInState).toEqual({ - username: user1.username, - challengeName: user1.challengeName, - signInSession: user1.signInSession, - }); - - signInStore.dispatch({ - type: 'SET_SIGN_IN_SESSION', - value: newSignInSessionID, - }); - - expect(persistSignInStateSpy).toHaveBeenCalledTimes(1); - expect(persistSignInStateSpy).toHaveBeenCalledWith({ - signInSession: newSignInSessionID, - }); - const newLocalSignInState = signInStore.getState(); - expect(newLocalSignInState).toEqual({ - username: user1.username, - challengeName: user1.challengeName, - signInSession: newSignInSessionID, - }); - }); - - test('State Challenge Name is updated after dispatching custom challenge name', () => { - const newChallengeName = 'RANDOM_CHALLENGE' as ChallengeName; - - populateValidTestSyncStorage(); - - const localSignInState = signInStore.getState(); - expect(localSignInState).toEqual({ - username: user1.username, - challengeName: user1.challengeName, - signInSession: user1.signInSession, - }); - - signInStore.dispatch({ - type: 'SET_CHALLENGE_NAME', - value: newChallengeName, - }); - - const newLocalSignInState = signInStore.getState(); - expect(newLocalSignInState).toEqual({ - username: user1.username, - challengeName: newChallengeName, - signInSession: user1.signInSession, - }); - }); -}); diff --git a/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts b/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts index 5e43c1c7636..80006cbf675 100644 --- a/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInStateManagement.test.ts @@ -30,7 +30,6 @@ describe('local sign-in state management tests', () => { beforeEach(() => { cognitoUserPoolsTokenProvider.setAuthConfig(authConfig); - signInStore.dispatch({ type: 'RESET_STATE' }); }); test('local state management should return state after signIn returns a ChallengeName', async () => { diff --git a/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts b/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts index 486d4fd9a81..8f91323319f 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts @@ -42,20 +42,7 @@ jest.mock('@aws-amplify/core', () => { getConfig: jest.fn(() => mockAuthConfigWithOAuth), [ACTUAL_ADD_OAUTH_LISTENER]: jest.fn(), }, - ConsoleLogger: jest.fn().mockImplementation(() => { - return { warn: jest.fn() }; - }), - syncSessionStorage: { - setItem: jest.fn((key, value) => { - window.sessionStorage.setItem(key, value); - }), - getItem: jest.fn((key: string) => { - return window.sessionStorage.getItem(key); - }), - removeItem: jest.fn((key: string) => { - window.sessionStorage.removeItem(key); - }), - }, + ConsoleLogger: jest.fn(), }; }); diff --git a/packages/auth/src/providers/cognito/apis/confirmSignIn.ts b/packages/auth/src/providers/cognito/apis/confirmSignIn.ts index eb51651eaed..b8e8475aa42 100644 --- a/packages/auth/src/providers/cognito/apis/confirmSignIn.ts +++ b/packages/auth/src/providers/cognito/apis/confirmSignIn.ts @@ -10,7 +10,11 @@ import { VerifySoftwareTokenException, } from '../types/errors'; import { ConfirmSignInInput, ConfirmSignInOutput } from '../types'; -import { setActiveSignInState, signInStore } from '../utils/signInStore'; +import { + cleanActiveSignInState, + setActiveSignInState, + signInStore, +} from '../utils/signInStore'; import { AuthError } from '../../../errors/AuthError'; import { getNewDeviceMetadata, @@ -105,8 +109,7 @@ export async function confirmSignIn( }); if (AuthenticationResult) { - signInStore.dispatch({ type: 'RESET_STATE' }); - + cleanActiveSignInState(); await cacheCognitoTokens({ username, ...AuthenticationResult, diff --git a/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts b/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts index e783f1fff3f..a666fba0acb 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithCustomAuth.ts @@ -21,7 +21,10 @@ import { SignInWithCustomAuthInput, SignInWithCustomAuthOutput, } from '../types'; -import { setActiveSignInState, signInStore } from '../utils/signInStore'; +import { + cleanActiveSignInState, + setActiveSignInState, +} from '../utils/signInStore'; import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { ChallengeName, @@ -81,7 +84,7 @@ export async function signInWithCustomAuth( signInDetails, }); if (AuthenticationResult) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); await cacheCognitoTokens({ username: activeUsername, @@ -108,7 +111,7 @@ export async function signInWithCustomAuth( challengeParameters: retiredChallengeParameters as ChallengeParameters, }); } catch (error) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); assertServiceError(error); const result = getSignInResultFromError(error.name); if (result) return result; diff --git a/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts b/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts index b5e44f2937c..a22f98b3804 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithCustomSRPAuth.ts @@ -23,7 +23,10 @@ import { SignInWithCustomSRPAuthInput, SignInWithCustomSRPAuthOutput, } from '../types'; -import { setActiveSignInState, signInStore } from '../utils/signInStore'; +import { + cleanActiveSignInState, + setActiveSignInState, +} from '../utils/signInStore'; import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { ChallengeName, @@ -86,7 +89,6 @@ export async function signInWithCustomSRPAuth( signInDetails, }); if (AuthenticationResult) { - signInStore.dispatch({ type: 'RESET_STATE' }); await cacheCognitoTokens({ username: activeUsername, ...AuthenticationResult, @@ -98,6 +100,7 @@ export async function signInWithCustomSRPAuth( }), signInDetails, }); + cleanActiveSignInState(); await dispatchSignedInHubEvent(); @@ -112,7 +115,7 @@ export async function signInWithCustomSRPAuth( challengeParameters: handledChallengeParameters as ChallengeParameters, }); } catch (error) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); assertServiceError(error); const result = getSignInResultFromError(error.name); if (result) return result; diff --git a/packages/auth/src/providers/cognito/apis/signInWithSRP.ts b/packages/auth/src/providers/cognito/apis/signInWithSRP.ts index 5e7cb57a08e..9bb8d4deca7 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithSRP.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithSRP.ts @@ -27,7 +27,10 @@ import { SignInWithSRPInput, SignInWithSRPOutput, } from '../types'; -import { setActiveSignInState, signInStore } from '../utils/signInStore'; +import { + cleanActiveSignInState, + setActiveSignInState, +} from '../utils/signInStore'; import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { tokenOrchestrator } from '../tokenProvider'; import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; @@ -86,7 +89,7 @@ export async function signInWithSRP( signInDetails, }); if (AuthenticationResult) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); await cacheCognitoTokens({ username: activeUsername, ...AuthenticationResult, @@ -112,7 +115,7 @@ export async function signInWithSRP( challengeParameters: handledChallengeParameters as ChallengeParameters, }); } catch (error) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); assertServiceError(error); const result = getSignInResultFromError(error.name); if (result) return result; diff --git a/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts b/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts index 01cfb868924..071f54f8313 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithUserPassword.ts @@ -25,7 +25,10 @@ import { SignInWithUserPasswordInput, SignInWithUserPasswordOutput, } from '../types'; -import { setActiveSignInState, signInStore } from '../utils/signInStore'; +import { + cleanActiveSignInState, + setActiveSignInState, +} from '../utils/signInStore'; import { cacheCognitoTokens } from '../tokenProvider/cacheTokens'; import { tokenOrchestrator } from '../tokenProvider'; import { dispatchSignedInHubEvent } from '../utils/dispatchSignedInHubEvent'; @@ -81,7 +84,6 @@ export async function signInWithUserPassword( signInDetails, }); if (AuthenticationResult) { - signInStore.dispatch({ type: 'RESET_STATE' }); await cacheCognitoTokens({ ...AuthenticationResult, username: activeUsername, @@ -93,6 +95,7 @@ export async function signInWithUserPassword( }), signInDetails, }); + cleanActiveSignInState(); await dispatchSignedInHubEvent(); @@ -107,7 +110,7 @@ export async function signInWithUserPassword( challengeParameters: retriedChallengeParameters as ChallengeParameters, }); } catch (error) { - signInStore.dispatch({ type: 'RESET_STATE' }); + cleanActiveSignInState(); assertServiceError(error); const result = getSignInResultFromError(error.name); if (result) return result; diff --git a/packages/auth/src/providers/cognito/utils/signInStore.ts b/packages/auth/src/providers/cognito/utils/signInStore.ts index 748e6f0eccf..fd07cb15e6d 100644 --- a/packages/auth/src/providers/cognito/utils/signInStore.ts +++ b/packages/auth/src/providers/cognito/utils/signInStore.ts @@ -1,8 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { syncSessionStorage } from '@aws-amplify/core'; - import { CognitoAuthSignInDetails } from '../types'; import { ChallengeName } from '../../../foundation/factories/serviceClients/cognitoIdentityProvider/types'; @@ -19,8 +17,7 @@ type SignInAction = | { type: 'SET_SIGN_IN_STATE'; value: SignInState } | { type: 'SET_USERNAME'; value?: string } | { type: 'SET_CHALLENGE_NAME'; value?: ChallengeName } - | { type: 'SET_SIGN_IN_SESSION'; value?: string } - | { type: 'RESET_STATE' }; + | { type: 'SET_SIGN_IN_SESSION'; value?: string }; type Store = (reducer: Reducer) => { getState(): ReturnType>; @@ -29,110 +26,44 @@ type Store = (reducer: Reducer) => { type Reducer = (state: State, action: Action) => State; -// Minutes until stored session invalidates -const MS_TO_EXPIRY = 3 * 60 * 1000; // 3 mins -const TGT_STATE = 'CognitoSignInState'; -const SIGN_IN_STATE_KEYS = { - username: `${TGT_STATE}.username`, - challengeName: `${TGT_STATE}.challengeName`, - signInSession: `${TGT_STATE}.signInSession`, - expiry: `${TGT_STATE}.expiry`, -}; - const signInReducer: Reducer = (state, action) => { switch (action.type) { case 'SET_SIGN_IN_SESSION': - persistSignInState({ signInSession: action.value }); - return { ...state, signInSession: action.value, }; - case 'SET_SIGN_IN_STATE': - persistSignInState(action.value); - return { ...action.value, }; - case 'SET_CHALLENGE_NAME': - persistSignInState({ challengeName: action.value }); - return { ...state, challengeName: action.value, }; - case 'SET_USERNAME': - persistSignInState({ username: action.value }); - return { ...state, username: action.value, }; - case 'SET_INITIAL_STATE': - return initializeState(); - - case 'RESET_STATE': - clearPersistedSignInState(); - - return getDefaultState(); - - // this state is never reachable + return defaultState(); default: return state; } }; -const isExpired = (expiryDate: string | null): boolean => { - const expiryTimestamp = Number(expiryDate); - const currentTimestamp = Date.now(); - - return expiryTimestamp <= currentTimestamp; -}; - -const clearPersistedSignInState = () => { - for (const storedKey of Object.values(SIGN_IN_STATE_KEYS)) { - syncSessionStorage.removeItem(storedKey); - } -}; - -const getDefaultState = (): SignInState => ({ - username: undefined, - challengeName: undefined, - signInSession: undefined, -}); - -// Hydrate signInStore from Synced Session Storage -const initializeState = (): SignInState => { - const expiry = syncSessionStorage.getItem(SIGN_IN_STATE_KEYS.expiry); - - if (!expiry || (expiry && isExpired(expiry))) { - clearPersistedSignInState(); - - return getDefaultState(); - } else { - const username = - syncSessionStorage.getItem(SIGN_IN_STATE_KEYS.username) ?? undefined; - - const challengeName = (syncSessionStorage.getItem( - SIGN_IN_STATE_KEYS.challengeName, - ) ?? undefined) as ChallengeName; - const signInSession = - syncSessionStorage.getItem(SIGN_IN_STATE_KEYS.signInSession) ?? undefined; - - return { - username, - challengeName, - signInSession, - }; - } -}; +function defaultState(): SignInState { + return { + username: undefined, + challengeName: undefined, + signInSession: undefined, + }; +} const createStore: Store = reducer => { - let currentState = reducer(getDefaultState(), { type: 'SET_INITIAL_STATE' }); + let currentState = reducer(defaultState(), { type: 'SET_INITIAL_STATE' }); return { getState: () => currentState, @@ -151,23 +82,6 @@ export function setActiveSignInState(state: SignInState): void { }); } -// Save local state into Session Storage -export const persistSignInState = ({ - challengeName, - signInSession, - username, -}: SignInState) => { - username && syncSessionStorage.setItem(SIGN_IN_STATE_KEYS.username, username); - challengeName && - syncSessionStorage.setItem(SIGN_IN_STATE_KEYS.challengeName, challengeName); - - if (signInSession) { - syncSessionStorage.setItem(SIGN_IN_STATE_KEYS.signInSession, signInSession); - - // Updates expiry when session is passed - syncSessionStorage.setItem( - SIGN_IN_STATE_KEYS.expiry, - String(Date.now() + MS_TO_EXPIRY), - ); - } -}; +export function cleanActiveSignInState(): void { + signInStore.dispatch({ type: 'SET_INITIAL_STATE' }); +} diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index d87979bcba3..be4869398ad 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -383,7 +383,7 @@ "name": "[Auth] confirmSignIn (Cognito)", "path": "./dist/esm/auth/index.mjs", "import": "{ confirmSignIn }", - "limit": "28.60 kB" + "limit": "28.39 kB" }, { "name": "[Auth] updateMFAPreference (Cognito)", @@ -449,7 +449,7 @@ "name": "[Auth] Basic Auth Flow (Cognito)", "path": "./dist/esm/auth/index.mjs", "import": "{ signIn, signOut, fetchAuthSession, confirmSignIn }", - "limit": "30.45 kB" + "limit": "30.23 kB" }, { "name": "[Auth] OAuth Auth Flow (Cognito)", @@ -497,7 +497,7 @@ "name": "[Storage] uploadData (S3)", "path": "./dist/esm/storage/index.mjs", "import": "{ uploadData }", - "limit": "19.99 kB" + "limit": "19.95 kB" } ] } diff --git a/packages/core/__tests__/storage/SyncSessionStorage.test.ts b/packages/core/__tests__/storage/SyncSessionStorage.test.ts deleted file mode 100644 index 5b27081891b..00000000000 --- a/packages/core/__tests__/storage/SyncSessionStorage.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -import { SyncSessionStorage } from '../../src/storage/SyncSessionStorage'; - -describe('SyncSessionStorage', () => { - let sessionStorage: SyncSessionStorage; - const signInStateKeys: Record = { - username: 'CognitoSignInState.username', - challengeName: 'CognitoSignInState.challengeName', - signInSession: 'CognitoSignInState.signInSession', - expiry: 'CognitoSignInState.expiry', - }; - - const user1 = { - username: 'joonchoi', - challengeName: 'CUSTOM_CHALLENGE', - signInSession: '888577-ltfgo-42d8-891d-666l858766g7', - expiry: '1234567', - }; - - beforeEach(() => { - sessionStorage = new SyncSessionStorage(); - }); - - it('can set and retrieve item by key', () => { - sessionStorage.setItem(signInStateKeys.username, user1.username); - sessionStorage.setItem(signInStateKeys.challengeName, user1.challengeName); - sessionStorage.setItem(signInStateKeys.signInSession, user1.signInSession); - sessionStorage.setItem(signInStateKeys.expiry, user1.expiry); - - expect(sessionStorage.getItem(signInStateKeys.username)).toBe( - user1.username, - ); - expect(sessionStorage.getItem(signInStateKeys.challengeName)).toBe( - user1.challengeName, - ); - expect(sessionStorage.getItem(signInStateKeys.signInSession)).toBe( - user1.signInSession, - ); - expect(sessionStorage.getItem(signInStateKeys.expiry)).toBe(user1.expiry); - }); - - it('can override item by setting with the same key', () => { - const newUserName = 'joonchoi+test'; - sessionStorage.setItem(signInStateKeys.username, user1.username); - sessionStorage.setItem(signInStateKeys.username, newUserName); - - expect(sessionStorage.getItem(signInStateKeys.username)).toBe(newUserName); - }); - - it('can remove item by key', () => { - const newUserName = 'joonchoi+tobedeleted'; - sessionStorage.setItem(signInStateKeys.username, newUserName); - expect(sessionStorage.getItem(signInStateKeys.username)).toBe(newUserName); - sessionStorage.removeItem(signInStateKeys.username); - expect(sessionStorage.getItem(signInStateKeys.username)).toBeNull(); - }); - - it('clears all items', () => { - sessionStorage.setItem(signInStateKeys.username, user1.username); - sessionStorage.setItem(signInStateKeys.challengeName, user1.challengeName); - sessionStorage.setItem(signInStateKeys.signInSession, user1.signInSession); - sessionStorage.setItem(signInStateKeys.expiry, user1.expiry); - - sessionStorage.clear(); - - expect(sessionStorage.getItem(signInStateKeys.username)).toBeNull(); - expect(sessionStorage.getItem(signInStateKeys.challengeName)).toBeNull(); - expect(sessionStorage.getItem(signInStateKeys.signInSession)).toBeNull(); - expect(sessionStorage.getItem(signInStateKeys.expiry)).toBeNull(); - }); - - it('will not throw if trying to delete a non existing key', () => { - const badKey = 'nonExistingKey'; - - expect(() => { - sessionStorage.removeItem(badKey); - }).not.toThrow(); - }); -}); diff --git a/packages/core/__tests__/storage/storage-mechanisms-node-runtime.test.ts b/packages/core/__tests__/storage/storage-mechanisms-node-runtime.test.ts new file mode 100644 index 00000000000..0566237962b --- /dev/null +++ b/packages/core/__tests__/storage/storage-mechanisms-node-runtime.test.ts @@ -0,0 +1,29 @@ +/** + * @jest-environment node + */ + +import { AmplifyError, AmplifyErrorCode } from '../../src/libraryUtils'; +import { defaultStorage, sessionStorage } from '../../src/storage'; + +const key = 'k'; +const value = 'value'; + +describe('test mechanisms', () => { + test('test defaultStorage operations in node environment', async () => { + try { + await defaultStorage.setItem(key, value); + } catch (error: any) { + expect(error).toBeInstanceOf(AmplifyError); + expect(error.name).toBe(AmplifyErrorCode.PlatformNotSupported); + } + }); + + test('test sessionStorage operations in node environment', async () => { + try { + await sessionStorage.setItem(key, value); + } catch (error: any) { + expect(error).toBeInstanceOf(AmplifyError); + expect(error.name).toBe(AmplifyErrorCode.PlatformNotSupported); + } + }); +}); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 2ead3026682..f17968928c6 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -59,7 +59,6 @@ export { CookieStorage, defaultStorage, sessionStorage, - syncSessionStorage, sharedInMemoryStorage, } from './storage'; export { KeyValueStorageInterface } from './types'; diff --git a/packages/core/src/storage/SyncKeyValueStorage.ts b/packages/core/src/storage/SyncKeyValueStorage.ts deleted file mode 100644 index 33885f2af31..00000000000 --- a/packages/core/src/storage/SyncKeyValueStorage.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { PlatformNotSupportedError } from '../errors'; -import { SyncStorage } from '../types'; - -/** - * @internal - */ -export class SyncKeyValueStorage implements SyncStorage { - _storage?: Storage; - - constructor(storage?: Storage) { - this._storage = storage; - } - - get storage() { - if (!this._storage) throw new PlatformNotSupportedError(); - - return this._storage; - } - - /** - * This is used to set a specific item in storage - * @param {string} key - the key for the item - * @param {object} value - the value - * @returns {string} value that was set - */ - setItem(key: string, value: string) { - this.storage.setItem(key, value); - } - - /** - * This is used to get a specific key from storage - * @param {string} key - the key for the item - * This is used to clear the storage - * @returns {string} the data item - */ - getItem(key: string) { - return this.storage.getItem(key); - } - - /** - * This is used to remove an item from storage - * @param {string} key - the key being set - * @returns {string} value - value that was deleted - */ - removeItem(key: string) { - this.storage.removeItem(key); - } - - /** - * This is used to clear the storage - * @returns {string} nothing - */ - clear() { - this.storage.clear(); - } -} diff --git a/packages/core/src/storage/SyncSessionStorage.ts b/packages/core/src/storage/SyncSessionStorage.ts deleted file mode 100644 index 83224bfc878..00000000000 --- a/packages/core/src/storage/SyncSessionStorage.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { SyncKeyValueStorage } from './SyncKeyValueStorage'; -import { getSessionStorageWithFallback } from './utils'; - -/** - * @internal - */ -export class SyncSessionStorage extends SyncKeyValueStorage { - constructor() { - super(getSessionStorageWithFallback()); - } -} diff --git a/packages/core/src/storage/index.ts b/packages/core/src/storage/index.ts index 72219167521..29fba0b3dea 100644 --- a/packages/core/src/storage/index.ts +++ b/packages/core/src/storage/index.ts @@ -5,11 +5,9 @@ import { DefaultStorage } from './DefaultStorage'; import { InMemoryStorage } from './InMemoryStorage'; import { KeyValueStorage } from './KeyValueStorage'; import { SessionStorage } from './SessionStorage'; -import { SyncSessionStorage } from './SyncSessionStorage'; export { CookieStorage } from './CookieStorage'; export const defaultStorage = new DefaultStorage(); export const sessionStorage = new SessionStorage(); -export const syncSessionStorage = new SyncSessionStorage(); export const sharedInMemoryStorage = new KeyValueStorage(new InMemoryStorage()); diff --git a/packages/core/src/types/storage.ts b/packages/core/src/types/storage.ts index 79a0c63e74b..d664a95b446 100644 --- a/packages/core/src/types/storage.ts +++ b/packages/core/src/types/storage.ts @@ -21,10 +21,3 @@ export interface CookieStorageData { secure?: boolean; sameSite?: SameSite; } - -export interface SyncStorage { - setItem(key: string, value: string): void; - getItem(key: string): string | null; - removeItem(key: string): void; - clear(): void; -}