Skip to content
Open
3 changes: 2 additions & 1 deletion src/components/AnonymousReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ function AnonymousReportFooter({reportID}: AnonymousReportFooterProps) {
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {windowWidth} = useWindowDimensions();
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
const [session] = useOnyx(ONYXKEYS.SESSION);
const isSmallSizeLayout = windowWidth - (shouldUseNarrowLayout ? 0 : variables.sideBarWithLHBWidth) < variables.anonymousReportFooterBreakpoint || isInSidePanel;

return (
Expand All @@ -54,7 +55,7 @@ function AnonymousReportFooter({reportID}: AnonymousReportFooterProps) {
success
text={translate('common.signIn')}
onPress={() => {
signOutAndRedirectToSignIn();
signOutAndRedirectToSignIn(undefined, undefined, true, undefined, session);
}}
/>
</View>
Expand Down
7 changes: 6 additions & 1 deletion src/components/ConnectToHRFlow/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import useEnvironment from '@hooks/useEnvironment';
import useOnyx from '@hooks/useOnyx';

import {openLink} from '@userActions/Link';

import ONYXKEYS from '@src/ONYXKEYS';

import {useEffect} from 'react';

import type ConnectToHRFlowProps from './types';

function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
const {environmentURL} = useEnvironment();
const [session] = useOnyx(ONYXKEYS.SESSION);

useEffect(() => {
openLink(setupLink, environmentURL);
openLink(setupLink, environmentURL, false, session);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [environmentURL, setupLink]);

return null;
Expand Down
6 changes: 5 additions & 1 deletion src/components/ConnectToQuickbooksOnlineFlow/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import useEnvironment from '@hooks/useEnvironment';
import useOnyx from '@hooks/useOnyx';

import {getQuickbooksOnlineSetupLink} from '@libs/actions/connections/QuickbooksOnline';

import {openLink} from '@userActions/Link';

import ONYXKEYS from '@src/ONYXKEYS';

import type {ConnectToQuickbooksOnlineFlowProps} from './types';

import BaseConnectToQuickbooksOnlineFlow from './BaseConnectToQuickbooksOnlineFlow';

function ConnectToQuickbooksOnlineFlow({policyID, isIntuitEnterpriseSuite}: ConnectToQuickbooksOnlineFlowProps) {
const {environmentURL} = useEnvironment();
const [session] = useOnyx(ONYXKEYS.SESSION);

return (
<BaseConnectToQuickbooksOnlineFlow
policyID={policyID}
isIntuitEnterpriseSuite={isIntuitEnterpriseSuite}
onConnect={(isSandbox) => {
// On web the setup opens OldDot in a new browser tab.
openLink(getQuickbooksOnlineSetupLink(policyID, isIntuitEnterpriseSuite, isSandbox), environmentURL);
openLink(getQuickbooksOnlineSetupLink(policyID, isIntuitEnterpriseSuite, isSandbox), environmentURL, false, session);
}}
/>
);
Expand Down
6 changes: 5 additions & 1 deletion src/components/ConnectToXeroFlow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import RequireTwoFactorAuthenticationModal from '@components/RequireTwoFactorAut

import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useTwoFactorAuthRoute from '@hooks/useTwoFactorAuthRoute';

import {getXeroSetupLink} from '@libs/actions/connections/Xero';
Expand All @@ -10,13 +11,16 @@ import Navigation from '@libs/Navigation/Navigation';

import {openLink} from '@userActions/Link';

import ONYXKEYS from '@src/ONYXKEYS';

import React, {useEffect, useState} from 'react';

import type {ConnectToXeroFlowProps} from './types';

function ConnectToXeroFlow({policyID}: ConnectToXeroFlowProps) {
const {translate} = useLocalize();
const {environmentURL} = useEnvironment();
const [session] = useOnyx(ONYXKEYS.SESSION);

const {is2FAEnabled, getTwoFactorAuthRoute} = useTwoFactorAuthRoute();

Expand All @@ -29,7 +33,7 @@ function ConnectToXeroFlow({policyID}: ConnectToXeroFlowProps) {
}
// On web the setup opens OldDot in a new browser tab. Open it inline here (within the connect click's
// user-gesture window) instead of navigating to a setup screen, otherwise the popup blocker stops the tab.
openLink(getXeroSetupLink(policyID), environmentURL);
openLink(getXeroSetupLink(policyID), environmentURL, false, session);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TextLink from '@components/TextLink';

import useEnvironment from '@hooks/useEnvironment';
import useHover from '@hooks/useHover';
import useOnyx from '@hooks/useOnyx';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -14,6 +15,7 @@ import {getInternalExpensifyPath, getInternalNewExpensifyPath, openLink} from '@
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

import type {StyleProp, TextStyle} from 'react-native';
import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html';
Expand All @@ -36,6 +38,7 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
const StyleUtils = useStyleUtils();
const htmlAttribs = tnode.attributes;
const {environmentURL} = useEnvironment();
const [session] = useOnyx(ONYXKEYS.SESSION);
const {hovered, bind} = useHover();
// An auth token is needed to download Expensify chat attachments
const isAttachment = !!htmlAttribs[CONST.ATTACHMENT_SOURCE_ATTRIBUTE];
Expand All @@ -60,11 +63,11 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {

const onLinkPress = useMemo(() => {
if (internalNewExpensifyPath || internalExpensifyPath) {
return () => openLink(attrHref, environmentURL, isAttachment);
return () => openLink(attrHref, environmentURL, isAttachment, session);
}

return undefined;
}, [internalNewExpensifyPath, internalExpensifyPath, attrHref, environmentURL, isAttachment]);
}, [internalNewExpensifyPath, internalExpensifyPath, attrHref, environmentURL, isAttachment, session]);

// The table row already navigates to this link's destination, so the cell shows the link text as plain content
// rather than a second target styled as a link.
Expand Down Expand Up @@ -123,7 +126,7 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
return (
<TextLink
style={linkStyle}
onPress={() => openLink(attrHref, environmentURL, isAttachment)}
onPress={() => openLink(attrHref, environmentURL, isAttachment, session)}
suppressDefaultStyle
>
<TNodeChildrenRenderer tnode={tnode} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useEnvironment from '@hooks/useEnvironment';
import useHover from '@hooks/useHover';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';

Expand All @@ -14,6 +15,7 @@ import {openLink} from '@libs/actions/Link';
import variables from '@styles/variables';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

import type {CustomRendererProps, TBlock, TNode} from 'react-native-render-html';

Expand Down Expand Up @@ -50,6 +52,7 @@ function TableRowRenderer({tnode}: CustomRendererProps<TBlock>) {
const {environmentURL} = useEnvironment();
const icons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
const {hovered, bind} = useHover();
const [session] = useOnyx(ONYXKEYS.SESSION);
const {anchor, report, action, originalReportID} = useShowContextMenuState();
const {onShowContextMenu, checkIfContextMenuActive} = useShowContextMenuActions();

Expand Down Expand Up @@ -90,7 +93,7 @@ function TableRowRenderer({tnode}: CustomRendererProps<TBlock>) {
<PressableWithoutFeedback
style={rowStyle}
hoverStyle={styles.htmlTableRowHovered}
onPress={() => openLink(rowLinkURL, environmentURL)}
onPress={() => openLink(rowLinkURL, environmentURL, undefined, session)}
onLongPress={(event) => onShowContextMenu(() => showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, originalReportID))}
role={CONST.ROLE.BUTTON}
accessibilityLabel={getRowCellsText(tnode) || translate('iou.viewDetails')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function ReportActionItemEmojiReactions({reportAction, reportID, isEditingInline
const {preferredLocale} = useLocalize();
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
const [preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE] = useOnyx(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE);
const [session] = useOnyx(ONYXKEYS.SESSION);

const reportActionID = reportAction.reportActionID;
const [emojiReactions = getEmptyObject<ReportActionReactions>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`);
Expand All @@ -93,7 +94,7 @@ function ReportActionItemEmojiReactions({reportAction, reportID, isEditingInline

TransitionTracker.runAfterTransitions({
callback: () => {
signOutAndRedirectToSignIn();
signOutAndRedirectToSignIn(undefined, undefined, true, undefined, session);
},
});
return;
Expand Down
5 changes: 4 additions & 1 deletion src/components/SubStepForms/DocusignFullStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import UploadFile from '@components/UploadFile';

import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useThemeStyles from '@hooks/useThemeStyles';

import mapCurrencyToCountry from '@libs/mapCurrencyToCountry';
Expand All @@ -17,6 +18,7 @@ import {clearErrorFields, clearErrors, setDraftValues, setErrorFields} from '@us
import {openLink} from '@userActions/Link';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxFormValuesMapping} from '@src/ONYXKEYS';
import type {FileObject} from '@src/types/utils/Attachment';

Expand Down Expand Up @@ -61,6 +63,7 @@ function DocusignFullStepImpl({defaultValue, formID, inputID, isLoading, onBackB
const {translate} = useLocalize();
const styles = useThemeStyles();
const {environmentURL} = useEnvironment();
const [session] = useOnyx(ONYXKEYS.SESSION);

const formRef = useRef<FormRef | null>(null);

Expand Down Expand Up @@ -135,7 +138,7 @@ function DocusignFullStepImpl({defaultValue, formID, inputID, isLoading, onBackB
size={CONST.BUTTON_SIZE.LARGE}
style={[styles.w100, styles.mb15]}
onPress={() => {
openLink(CONST.DOCUSIGN_POWERFORM_LINK[country as 'CA' | 'AU' | 'US'], environmentURL);
openLink(CONST.DOCUSIGN_POWERFORM_LINK[country as 'CA' | 'AU' | 'US'], environmentURL, false, session);
}}
>
<Button.Text>{translate('docusignStep.takeMeTo')}</Button.Text>
Expand Down
5 changes: 4 additions & 1 deletion src/components/TextLink.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import useEnvironment from '@hooks/useEnvironment';
import useOnyx from '@hooks/useOnyx';
import useThemeStyles from '@hooks/useThemeStyles';

import {openLink as openLinkUtil} from '@userActions/Link';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

import type {KeyboardEvent, KeyboardEventHandler, MouseEventHandler} from 'react';
import type {GestureResponderEvent, StyleProp, TextStyle} from 'react-native';
Expand Down Expand Up @@ -43,12 +45,13 @@ type TextLinkProps = (LinkProps | PressProps) &
function TextLink({href, onPress, children, style, onMouseDown = (event) => event.preventDefault(), suppressDefaultStyle = false, ref, ...rest}: TextLinkProps) {
const {environmentURL} = useEnvironment();
const styles = useThemeStyles();
const [session] = useOnyx(ONYXKEYS.SESSION);

const openLink = (event: GestureResponderEvent | KeyboardEvent) => {
if (onPress) {
onPress(event);
} else {
openLinkUtil(href, environmentURL);
openLinkUtil(href, environmentURL, false, session);
}
};

Expand Down
5 changes: 4 additions & 1 deletion src/components/TextLinkBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import useEnvironment from '@hooks/useEnvironment';
import useOnyx from '@hooks/useOnyx';
import useThemeStyles from '@hooks/useThemeStyles';

import {openLink as openLinkUtil} from '@userActions/Link';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

import type {StyleProp, TextStyle} from 'react-native';

Expand Down Expand Up @@ -36,12 +38,13 @@ function TextLinkBlock({text, style, prefixIcon, ...rest}: TextLinkBlockProps) {

const {environmentURL} = useEnvironment();
const styles = useThemeStyles();
const [session] = useOnyx(ONYXKEYS.SESSION);

const openLink = () => {
if (!rest.href) {
return;
}
openLinkUtil(rest.href, environmentURL);
openLinkUtil(rest.href, environmentURL, false, session);
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function AuthScreensInitHandler() {
const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS);
const isSupportalTransition = currentUrl.includes('authTokenType=support');
if (isLoggingInAsNewUser && isTransitioning) {
Session.signOutAndRedirectToSignIn(false, isSupportalTransition);
Session.signOutAndRedirectToSignIn(false, isSupportalTransition, true, undefined, session);
return () => {
Session.cleanupSession();
};
Expand Down
8 changes: 4 additions & 4 deletions src/libs/actions/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import {hasCompletedGuidedSetupFlowSelector} from '@src/selectors/Onboarding';
import type {Beta, IntroSelected, Report} from '@src/types/onyx';
import type {Beta, IntroSelected, Report, Session} from '@src/types/onyx';

import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';

Expand Down Expand Up @@ -385,7 +385,7 @@ function getReportLinkRoute(
return searchReportRoute;
}

function openLink(href: string, environmentURL: string, isAttachment = false) {
function openLink(href: string, environmentURL: string, isAttachment: boolean | undefined, session: OnyxEntry<Session>) {
const hasSameOrigin = Url.hasSameExpensifyOrigin(href, environmentURL);
const hasExpensifyOrigin = Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.EXPENSIFY_URL) || Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.STAGING_API_ROOT);
const internalNewExpensifyPath = getInternalNewExpensifyPath(href);
Expand Down Expand Up @@ -413,7 +413,7 @@ function openLink(href: string, environmentURL: string, isAttachment = false) {

if (reportLinkRoute) {
if (internalNewExpensifyPath && hasSameOrigin && isAnonymousUser() && !canAnonymousUserAccessRoute(internalNewExpensifyPath)) {
signOutAndRedirectToSignIn();
signOutAndRedirectToSignIn(undefined, undefined, undefined, undefined, session);
return;
}
if (focusedSearchReportActionRoute && reportLinkRouteParams?.reportActionID) {
Expand All @@ -431,7 +431,7 @@ function openLink(href: string, environmentURL: string, isAttachment = false) {
// instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag)
if (internalNewExpensifyPath && hasSameOrigin) {
if (isAnonymousUser() && !canAnonymousUserAccessRoute(internalNewExpensifyPath)) {
signOutAndRedirectToSignIn();
signOutAndRedirectToSignIn(undefined, undefined, undefined, undefined, session);
return;
}
if (shouldCloseRHP) {
Expand Down
16 changes: 11 additions & 5 deletions src/libs/actions/Session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,13 @@ const KEYS_TO_PRESERVE_SUPPORTAL = [
ONYXKEYS.COLLECTION.DEVICE_BIOMETRICS,
];

function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSession?: boolean, shouldSignOutFromOldDot = true, shouldForceUseStashedSession?: boolean) {
function signOutAndRedirectToSignIn(
shouldResetToHome?: boolean,
shouldStashSession?: boolean,
shouldSignOutFromOldDot = true,
shouldForceUseStashedSession?: boolean,
session: OnyxEntry<Session> = deprecatedSession,
) {
Log.info('Redirecting to Sign In because signOut() was called');
hideContextMenu(false);

Expand All @@ -367,7 +373,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
return;
}

const isSupportal = isSupportAuthToken();
const isSupportal = isSupportAuthToken(session);
const shouldRestoreStashedSession = isSupportal || shouldForceUseStashedSession;

if (CONFIG.IS_HYBRID_APP && shouldSignOutFromOldDot) {
Expand All @@ -379,7 +385,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
// session.
const signOutPromise: Promise<void | Response<never>> =
!shouldRestoreStashedSession && !shouldStashSession
? signOut({autoGeneratedLogin: credentials?.autoGeneratedLogin, signedInWithSAML: !!deprecatedSession.signedInWithSAML, authToken: deprecatedSession.authToken})
? signOut({autoGeneratedLogin: credentials?.autoGeneratedLogin, signedInWithSAML: !!session.signedInWithSAML, authToken: deprecatedSession.authToken})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the supplied session token for logout

When callers now pass an explicit session to avoid relying on module-level Onyx state, this branch still sends deprecatedSession.authToken to LOG_OUT/SAML while using the supplied session for the other logout decisions. If deprecatedSession is stale during an account/session transition, the server invalidates the wrong token or leaves the current token valid. Use session.authToken consistently here.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next PR, we will remove deprecatedSession. I'm not doing it in this PR because it would require a lot of changes.

: Promise.resolve();

// The function redirectToSignIn will clear the whole storage, so let's create our onyx params
Expand All @@ -392,7 +398,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
if (!isSupportal && shouldStashSession) {
onyxSetParams = {
[ONYXKEYS.STASHED_CREDENTIALS]: credentials,
[ONYXKEYS.STASHED_SESSION]: deprecatedSession,
[ONYXKEYS.STASHED_SESSION]: session,
};
}

Expand All @@ -414,7 +420,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
newDotCurrentAccountEmail: stashedSession.email ?? '',
authToken: stashedSession.authToken ?? '',
policyID: '',
accountID: deprecatedSession.accountID ? String(deprecatedSession.accountID) : '',
accountID: session.accountID ? String(session.accountID) : '',
});
hasSwitchedAccountInHybridMode = true;
}
Expand Down
Loading
Loading