diff --git a/src/components/AnchorForCommentsOnly/AnchorWithAuthToken.js b/src/components/AnchorForCommentsOnly/AnchorWithAuthToken.js
deleted file mode 100644
index 14440fc60dee..000000000000
--- a/src/components/AnchorForCommentsOnly/AnchorWithAuthToken.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import _ from 'underscore';
-import React from 'react';
-import PropTypes from 'prop-types';
-import {withOnyx} from 'react-native-onyx';
-import ONYXKEYS from '../../ONYXKEYS';
-import {
- propTypes as anchorForCommentsOnlyPropTypes,
- defaultProps as anchorForCommentsOnlyDefaultProps,
-} from './anchorForCommentsOnlyPropTypes';
-import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly';
-import addAuthTokenToURL from '../../libs/addAuthTokenToURL';
-
-const propTypes = {
- /** Session info for the currently logged in user. */
- session: PropTypes.shape({
- /** Currently logged in user authToken */
- authToken: PropTypes.string,
- }),
-
- ...anchorForCommentsOnlyPropTypes,
-};
-
-const defaultProps = {
- session: {
- authToken: null,
- },
- ...anchorForCommentsOnlyDefaultProps,
-};
-
-const AnchorWithAuthToken = (props) => {
- const urlWithAuthToken = addAuthTokenToURL({
- url: props.href,
- authToken: props.session.authToken,
- });
- const propsToPass = _.omit(props, 'session');
- propsToPass.href = urlWithAuthToken;
- propsToPass.shouldDownloadFile = true;
- // eslint-disable-next-line react/jsx-props-no-spreading
- return ;
-};
-
-AnchorWithAuthToken.propTypes = propTypes;
-AnchorWithAuthToken.defaultProps = defaultProps;
-AnchorWithAuthToken.displayName = 'AnchorWithAuthToken';
-
-export default withOnyx({
- session: {
- key: ONYXKEYS.SESSION,
- },
-})(AnchorWithAuthToken);
diff --git a/src/components/AnchorForCommentsOnly/index.js b/src/components/AnchorForCommentsOnly/index.js
index 6a5daf6a672b..080324d755d6 100644
--- a/src/components/AnchorForCommentsOnly/index.js
+++ b/src/components/AnchorForCommentsOnly/index.js
@@ -5,8 +5,8 @@ import {
propTypes as anchorForCommentsOnlyPropTypes,
defaultProps as anchorForCommentsOnlyDefaultProps,
} from './anchorForCommentsOnlyPropTypes';
-import AnchorWithAuthToken from './AnchorWithAuthToken';
import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly';
+import addEncryptedAuthTokenToURL from '../../libs/addEncryptedAuthTokenToURL';
const propTypes = {
/** Do we need an auth token to view this link or download the remote resource? */
@@ -27,11 +27,12 @@ const defaultProps = {
*/
const AnchorForCommentsOnly = (props) => {
const propsToPass = _.omit(props, 'isAuthTokenRequired');
- return props.isAuthTokenRequired
- // eslint-disable-next-line react/jsx-props-no-spreading
- ?
- // eslint-disable-next-line react/jsx-props-no-spreading
- : ;
+ if (props.isAuthTokenRequired) {
+ propsToPass.href = addEncryptedAuthTokenToURL(props.href);
+ propsToPass.shouldDownloadFile = true;
+ }
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ return ;
};
AnchorForCommentsOnly.propTypes = propTypes;
diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js
index 599456e55442..6207fa5bb2f8 100755
--- a/src/components/AttachmentModal.js
+++ b/src/components/AttachmentModal.js
@@ -2,14 +2,12 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import Str from 'expensify-common/lib/str';
-import {withOnyx} from 'react-native-onyx';
import CONST from '../CONST';
import Modal from './Modal';
import AttachmentView from './AttachmentView';
import styles from '../styles/styles';
import themeColors from '../styles/themes/default';
-import ONYXKEYS from '../ONYXKEYS';
-import addAuthTokenToURL from '../libs/addAuthTokenToURL';
+import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL';
import compose from '../libs/compose';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
import Button from './Button';
@@ -41,11 +39,6 @@ const propTypes = {
/** Do the urls require an authToken? */
isAuthTokenRequired: PropTypes.bool,
- /** Current user session */
- session: PropTypes.shape({
- authToken: PropTypes.string.isRequired,
- }).isRequired,
-
...withLocalizePropTypes,
...windowDimensionsPropTypes,
@@ -89,11 +82,9 @@ class AttachmentModal extends PureComponent {
}
render() {
- const sourceURL = addAuthTokenToURL({
- url: this.state.sourceURL,
- authToken: this.props.session.authToken,
- required: this.props.isAuthTokenRequired,
- });
+ const sourceURL = this.props.isAuthTokenRequired
+ ? addEncryptedAuthTokenToURL(this.state.sourceURL)
+ : this.state.sourceURL;
const attachmentViewStyles = this.props.isSmallScreenWidth
? [styles.imageModalImageCenterContainer]
@@ -164,10 +155,5 @@ AttachmentModal.propTypes = propTypes;
AttachmentModal.defaultProps = defaultProps;
export default compose(
withWindowDimensions,
- withOnyx({
- session: {
- key: ONYXKEYS.SESSION,
- },
- }),
withLocalize,
)(AttachmentModal);
diff --git a/src/components/ThumbnailImage.js b/src/components/ThumbnailImage.js
index 83280826602f..e1bebb06656a 100644
--- a/src/components/ThumbnailImage.js
+++ b/src/components/ThumbnailImage.js
@@ -1,10 +1,8 @@
import React, {PureComponent} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
-import {withOnyx} from 'react-native-onyx';
-import ONYXKEYS from '../ONYXKEYS';
import ImageWithSizeCalculation from './ImageWithSizeCalculation';
-import addAuthTokenToURL from '../libs/addAuthTokenToURL';
+import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL';
import styles, {getWidthAndHeightStyle} from '../styles/styles';
const propTypes = {
@@ -15,11 +13,6 @@ const propTypes = {
// eslint-disable-next-line react/forbid-prop-types
style: PropTypes.any,
- /** Current user session */
- session: PropTypes.shape({
- authToken: PropTypes.string.isRequired,
- }).isRequired,
-
/** Do the urls require an authToken? */
isAuthTokenRequired: PropTypes.bool.isRequired,
};
@@ -50,11 +43,9 @@ class ThumbnailImage extends PureComponent {
}
render() {
- const url = addAuthTokenToURL({
- url: this.props.previewSourceURL,
- authToken: this.props.session.authToken,
- required: this.props.isAuthTokenRequired,
- });
+ const url = this.props.isAuthTokenRequired
+ ? addEncryptedAuthTokenToURL(this.props.previewSourceURL)
+ : this.props.previewSourceURL;
return (
{
- const {authToken, email} = authenticateResponse;
- createTemporaryLogin(authToken, email);
+ const {authToken, encryptedAuthToken, email} = authenticateResponse;
+ createTemporaryLogin(authToken, encryptedAuthToken, email);
})
.catch((error) => {
Onyx.merge(ONYXKEYS.ACCOUNT, {error: error.message, loading: false});
@@ -256,7 +257,7 @@ function setPassword(password, validateCode, accountID) {
})
.then((response) => {
if (response.jsonCode === 200) {
- createTemporaryLogin(response.authToken, response.email);
+ createTemporaryLogin(response.authToken, response.encryptedAuthToken, response.email);
return;
}
diff --git a/src/libs/addAuthTokenToURL.js b/src/libs/addAuthTokenToURL.js
deleted file mode 100644
index 41c89590385b..000000000000
--- a/src/libs/addAuthTokenToURL.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Add authToken to this attachment URL if necessary
- *
- * @param {Object} parameters
- * @param {String} parameters.url
- * @param {Boolean} parameters.required
- * @param {String} parameters.authToken
- * @returns {String}
- */
-export default function ({url, authToken, required = true}) {
- return required
- ? `${url}?authToken=${authToken}`
- : url;
-}
diff --git a/src/libs/addEncryptedAuthTokenToURL.js b/src/libs/addEncryptedAuthTokenToURL.js
new file mode 100644
index 000000000000..82c4c1ac640f
--- /dev/null
+++ b/src/libs/addEncryptedAuthTokenToURL.js
@@ -0,0 +1,19 @@
+import lodashGet from 'lodash/get';
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../ONYXKEYS';
+
+let encryptedAuthToken = '';
+Onyx.connect({
+ key: ONYXKEYS.SESSION,
+ callback: session => encryptedAuthToken = lodashGet(session, 'encryptedAuthToken', ''),
+});
+
+/**
+ * Add encryptedAuthToken to this attachment URL
+ *
+ * @param {String} url
+ * @returns {String}
+ */
+export default function (url) {
+ return `${url}?encryptedAuthToken=${encryptedAuthToken}`;
+}
diff --git a/src/libs/migrateOnyx.js b/src/libs/migrateOnyx.js
index 8b0d428076c2..3466bc2606b6 100644
--- a/src/libs/migrateOnyx.js
+++ b/src/libs/migrateOnyx.js
@@ -1,3 +1,4 @@
+import AddEncryptedAuthToken from './migrations/AddEncryptedAuthToken';
import RenameActiveClientsKey from './migrations/RenameActiveClientsKey';
import RenamePriorityModeKey from './migrations/RenamePriorityModeKey';
@@ -10,6 +11,7 @@ export default function () {
const migrationPromises = [
RenameActiveClientsKey,
RenamePriorityModeKey,
+ AddEncryptedAuthToken,
];
// Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the
diff --git a/src/libs/migrations/AddEncryptedAuthToken.js b/src/libs/migrations/AddEncryptedAuthToken.js
new file mode 100644
index 000000000000..24660b4f3a91
--- /dev/null
+++ b/src/libs/migrations/AddEncryptedAuthToken.js
@@ -0,0 +1,41 @@
+import _ from 'underscore';
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../../ONYXKEYS';
+import {reauthenticate} from '../API';
+
+/**
+ * This migration adds an encryptedAuthToken to the SESSION key, if it is not present.
+ *
+ * @returns {Promise}
+ */
+export default function () {
+ return new Promise((resolve) => {
+ const connectionID = Onyx.connect({
+ key: ONYXKEYS.SESSION,
+ callback: (session) => {
+ Onyx.disconnect(connectionID);
+
+ if (session && !_.isEmpty(session.encryptedAuthToken)) {
+ console.debug('[Migrate Onyx] Skipped migration AddEncryptedAuthToken');
+ return resolve();
+ }
+
+ if (!session || !session.authToken) {
+ console.debug('[Migrate Onyx] Skipped migration AddEncryptedAuthToken');
+ return resolve();
+ }
+
+ // If there is an auth token but no encrypted auth token, reauthenticate.
+ if (session.authToken && _.isUndefined(session.encryptedAuthToken)) {
+ return reauthenticate('Onyx_Migration_AddEncryptedAuthToken')
+ .then(() => {
+ console.debug('[Migrate Onyx] Ran migration AddEncryptedAuthToken');
+ return resolve();
+ });
+ }
+
+ return resolve();
+ },
+ });
+ });
+}