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

feat(auth): Enable resumable SignIn #13483

Merged
merged 55 commits into from
Sep 23, 2024
Merged
Changes from 2 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
e78c8e4
Resumable Sign In
Jun 7, 2024
49bb952
Add clear after rehydration
Jun 7, 2024
611357a
Synchronous Session Storage implementation
Jun 11, 2024
8d3944b
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jun 11, 2024
814ccf3
Fix error dependency path
Jun 12, 2024
a413779
Modify init sequence
Jun 12, 2024
4532bc8
Bug fix
Jun 12, 2024
2dd0fd9
Move SyncSessionStorage to core
Jun 13, 2024
a54055e
Fix defaulting state
Jun 14, 2024
3816f2f
Fix calling wrong method
Jun 15, 2024
20cd812
Add Unittest for SyncSessionstorage
Jun 15, 2024
5f99aad
Adjust bundle size, fix exports
Jun 15, 2024
f040d10
Adjust bundle size, fix typo
Jun 15, 2024
c4642cf
Loosen jest cov for src/utils
Jun 15, 2024
8abe4d4
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jun 15, 2024
8237695
ResumableSignIn Unit Tests
Jun 20, 2024
b6d666e
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jun 20, 2024
e5a5b4d
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jun 21, 2024
bf370d2
Modified signInStore implementation
Jun 24, 2024
8077bb4
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jun 24, 2024
b91fec6
Complemented additional behaviors to address potential discrepancy du…
Jul 2, 2024
be3db29
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Jul 10, 2024
9f6c933
Modified State persistence behavior
Jul 10, 2024
82316a5
Update params
Jul 10, 2024
2c7600a
Add mock implementation to resolve test issue
Jul 10, 2024
08419ba
Changed expiration check logic
Jul 10, 2024
7e91d0f
Polish persistSignInState()
Jul 11, 2024
f22d805
Merge branch 'aws-amplify:main' into joonwonc/auth-resumable-signin
joon-won Aug 1, 2024
134e748
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 9, 2024
e0eed74
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 15, 2024
9a0d6d1
Adjust bundle size
Aug 15, 2024
363635d
Merge branch 'aws-amplify:main' into joonwonc/auth-resumable-signin
joon-won Aug 21, 2024
247ccc9
Add persisting action for session
Aug 21, 2024
539688b
Merge branch 'aws-amplify:main' into joonwonc/auth-resumable-signin
joon-won Aug 22, 2024
dea838e
Add spyOn checkpoints
Aug 22, 2024
deb0d9d
enable integ
Aug 23, 2024
aae163e
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 23, 2024
dbe8d02
Revert jest config for aws-amplify package test
Aug 23, 2024
7d0527c
revert workflow
Aug 23, 2024
c71e4ea
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 26, 2024
efb2331
Remove redundant features, improve efficiency
Aug 27, 2024
4899023
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 28, 2024
c4b043a
Adjust bundle size limit
Aug 28, 2024
3e54290
Remove redundancy, fix annotation
Aug 28, 2024
9f488c5
Replace cleanActiveSignInState()
Aug 28, 2024
6168bcb
Enable CI for Resumable SMS MFA
Aug 29, 2024
ed930f6
Merge branch 'joonwonc/auth-resumable-smsmfa' into joonwonc/auth-resu…
joon-won Aug 29, 2024
d19f72d
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Aug 30, 2024
1f120ab
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Sep 12, 2024
92ce212
Modify dependency to foundations
Sep 12, 2024
bd5b099
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Sep 13, 2024
224f148
Update Integ
Sep 13, 2024
0b0c518
Revert
Sep 13, 2024
5d4f6b5
Merge branch 'main' into joonwonc/auth-resumable-signin
joon-won Sep 20, 2024
a5326cc
Merge branch 'aws-amplify:main' into joonwonc/auth-resumable-signin
joon-won Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 83 additions & 7 deletions packages/auth/src/providers/cognito/utils/signInStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { ConsoleLogger } from '@aws-amplify/core';

import { CognitoAuthSignInDetails } from '../types';

import { ChallengeName } from './clients/CognitoIdentityProvider/types';
Expand All @@ -27,6 +29,22 @@

type Reducer<State, Action> = (state: State, action: Action) => State;

const logger = new ConsoleLogger('Auth signInStore');

// Minutes until stored session invalidates
const EXPIRATION_MINUTES = 5;
joon-won marked this conversation as resolved.
Show resolved Hide resolved
const MS_TO_EXPIRY = 1000 * 60 * EXPIRATION_MINUTES;
const SIGN_IN_STATE_KEYS = [
'username',
'challengeName',
'signInSession',
'expiry',
].reduce((keys: Record<string, string>, key) => {
keys[key] = `CognitoSignInState.${key}`;
joon-won marked this conversation as resolved.
Show resolved Hide resolved

return keys;
}, {});

const signInReducer: Reducer<SignInState, SignInAction> = (state, action) => {
switch (action.type) {
case 'SET_SIGN_IN_SESSION':
Expand All @@ -49,22 +67,61 @@
username: action.value,
};
case 'SET_INITIAL_STATE':
return defaultState();
return getInitialState();
joon-won marked this conversation as resolved.
Show resolved Hide resolved
default:
joon-won marked this conversation as resolved.
Show resolved Hide resolved
return state;
}
};

function defaultState(): SignInState {
const isExpired = (expiryDate: string): boolean => {
const expiryTimestamp = Number(expiryDate);
const currentTimestamp = Date.now();

return expiryTimestamp <= currentTimestamp;
};

const clearPersistedSignInState = () => {
joon-won marked this conversation as resolved.
Show resolved Hide resolved
for (const key in SIGN_IN_STATE_KEYS) {
sessionStorage.removeItem(key);
}
};

const getDefaultState = (): SignInState => ({
username: undefined,
challengeName: undefined,
signInSession: undefined,
});

// Hydrate signInStore from sessionStorage
const getInitialState = (): SignInState => {
const expiry = sessionStorage.getItem(SIGN_IN_STATE_KEYS.expiry) as string;
joon-won marked this conversation as resolved.
Show resolved Hide resolved
if (isExpired(expiry)) {
logger.warn('Sign-in session expired');
clearPersistedSignInState();

return getDefaultState();
}

const username =
sessionStorage.getItem(SIGN_IN_STATE_KEYS.username) ?? ('' as string);
joon-won marked this conversation as resolved.
Show resolved Hide resolved
const challengeName = (sessionStorage.getItem(
SIGN_IN_STATE_KEYS.challengeName,
) ?? '') as ChallengeName;
joon-won marked this conversation as resolved.
Show resolved Hide resolved
joon-won marked this conversation as resolved.
Show resolved Hide resolved
const signInSession =
sessionStorage.getItem(SIGN_IN_STATE_KEYS.signInSession) ?? ('' as string);
joon-won marked this conversation as resolved.
Show resolved Hide resolved

// Clear SignInStage from sessionStorage after re-hydration
clearPersistedSignInState();
joon-won marked this conversation as resolved.
Show resolved Hide resolved

return {
username: undefined,
challengeName: undefined,
signInSession: undefined,
username,
challengeName,
signInSession,
};
}
};

const createStore: Store<SignInState, SignInAction> = reducer => {
let currentState = reducer(defaultState(), { type: 'SET_INITIAL_STATE' });
let currentState = reducer(getDefaultState(), { type: 'SET_INITIAL_STATE' });
joon-won marked this conversation as resolved.
Show resolved Hide resolved

return {
getState: () => currentState,
Expand All @@ -81,8 +138,27 @@
type: 'SET_SIGN_IN_STATE',
value: state,
});

// Save the local state into sessionStorage
persistSignInState(state);
}

// Clear saved sign in states from both memory and sessionStorage
export function cleanActiveSignInState(): void {
signInStore.dispatch({ type: 'SET_INITIAL_STATE' });
clearPersistedSignInState();
}

const persistSignInState = ({
challengeName = '' as ChallengeName,
signInSession = '',
username = '',
joon-won marked this conversation as resolved.
Show resolved Hide resolved
}: SignInState) => {
sessionStorage.setItem(SIGN_IN_STATE_KEYS.username, username);
sessionStorage.setItem(SIGN_IN_STATE_KEYS.challengeName, challengeName);
Fixed Show fixed Hide fixed
sessionStorage.setItem(SIGN_IN_STATE_KEYS.signInSession, signInSession);
Fixed Show fixed Hide fixed
sessionStorage.setItem(
SIGN_IN_STATE_KEYS.expiry,
String(Date.now() + MS_TO_EXPIRY),
);
};
Loading