diff --git a/src/libs/Authentication.ts b/src/libs/Authentication.ts index dd1003591701..1ab7083b2d8e 100644 --- a/src/libs/Authentication.ts +++ b/src/libs/Authentication.ts @@ -1,6 +1,7 @@ import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import type Response from '@src/types/onyx/Response'; +import * as Delegate from './actions/Delegate'; import updateSessionAuthTokens from './actions/Session/updateSessionAuthTokens'; import redirectToSignIn from './actions/SignInRedirect'; import * as ErrorUtils from './ErrorUtils'; @@ -84,6 +85,14 @@ function reauthenticate(command = ''): Promise { return; } + // If we reauthenticated due to an expired delegate token, restore the delegate's original account. + // This is because the credentials used to reauthenticate were for the delegate's original account, and not for the account they were connected as. + if (Delegate.isConnectedAsDelegate()) { + Log.info('Reauthenticated while connected as a delegate. Restoring original account.'); + Delegate.restoreDelegateSession(response); + return; + } + // Update authToken in Onyx and in our local variables so that API requests will use the new authToken updateSessionAuthTokens(response.authToken, response.encryptedAuthToken); diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 573a8ca2ca63..2d6469dfb8a5 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -10,8 +10,10 @@ import * as SequentialQueue from '@libs/Network/SequentialQueue'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Delegate, DelegatedAccess, DelegateRole} from '@src/types/onyx/Account'; +import type Response from '@src/types/onyx/Response'; import {confirmReadyToOpenApp, openApp} from './App'; import updateSessionAuthTokens from './Session/updateSessionAuthTokens'; +import updateSessionUser from './Session/updateSessionUser'; let delegatedAccess: DelegatedAccess; Onyx.connect({ @@ -21,7 +23,18 @@ Onyx.connect({ }, }); -const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION, ONYXKEYS.IS_LOADING_APP]; +const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [ + ONYXKEYS.NVP_TRY_FOCUS_MODE, + ONYXKEYS.PREFERRED_THEME, + ONYXKEYS.NVP_PREFERRED_LOCALE, + ONYXKEYS.SESSION, + ONYXKEYS.IS_LOADING_APP, + ONYXKEYS.CREDENTIALS, + + // We need to preserve the sidebar loaded state since we never unrender the sidebar when connecting as a delegate + // This allows the report screen to load correctly when the delegate token expires and the delegate is returned to their original account. + ONYXKEYS.IS_SIDEBAR_LOADED, +]; function connect(email: string) { if (!delegatedAccess?.delegators) { @@ -313,6 +326,10 @@ function clearAddDelegateErrors(email: string, fieldName: string) { }); } +function isConnectedAsDelegate() { + return !!delegatedAccess?.delegate; +} + function removePendingDelegate(email: string) { if (!delegatedAccess?.delegates) { return; @@ -325,4 +342,17 @@ function removePendingDelegate(email: string) { }); } -export {connect, disconnect, clearDelegatorErrors, addDelegate, requestValidationCode, clearAddDelegateErrors, removePendingDelegate}; +function restoreDelegateSession(authenticateResponse: Response) { + Onyx.clear(KEYS_TO_PRESERVE_DELEGATE_ACCESS).then(() => { + updateSessionAuthTokens(authenticateResponse?.authToken, authenticateResponse?.encryptedAuthToken); + updateSessionUser(authenticateResponse?.accountID, authenticateResponse?.email); + + NetworkStore.setAuthToken(authenticateResponse.authToken ?? null); + NetworkStore.setIsAuthenticating(false); + + confirmReadyToOpenApp(); + openApp(); + }); +} + +export {connect, disconnect, clearDelegatorErrors, addDelegate, requestValidationCode, clearAddDelegateErrors, removePendingDelegate, restoreDelegateSession, isConnectedAsDelegate}; diff --git a/src/libs/actions/Session/updateSessionUser.ts b/src/libs/actions/Session/updateSessionUser.ts new file mode 100644 index 000000000000..75e888469bec --- /dev/null +++ b/src/libs/actions/Session/updateSessionUser.ts @@ -0,0 +1,6 @@ +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; + +export default function updateSessionUser(accountID?: number, email?: string) { + Onyx.merge(ONYXKEYS.SESSION, {accountID, email}); +} diff --git a/src/types/onyx/Response.ts b/src/types/onyx/Response.ts index ef558896c55e..3c12611ee841 100644 --- a/src/types/onyx/Response.ts +++ b/src/types/onyx/Response.ts @@ -68,6 +68,12 @@ type Response = { /** Base64 key to decrypt messages from Pusher encrypted channels */ // eslint-disable-next-line @typescript-eslint/naming-convention shared_secret?: string; + + /** The accountID of the user */ + accountID?: number; + + /** The email of the user */ + email?: string; }; export default Response;