Page MenuHomePhabricator

D12238.id40869.diff
No OneTemporary

D12238.id40869.diff

diff --git a/lib/shared/device-list-utils.js b/lib/shared/device-list-utils.js
--- a/lib/shared/device-list-utils.js
+++ b/lib/shared/device-list-utils.js
@@ -1,11 +1,14 @@
// @flow
+import invariant from 'invariant';
+
import type {
IdentityServiceClient,
RawDeviceList,
SignedDeviceList,
} from '../types/identity-service-types.js';
import { getConfig } from '../utils/config.js';
+import { getContentSigningKey } from '../utils/crypto-utils.js';
import {
composeRawDeviceList,
rawDeviceListFromSignedList,
@@ -134,4 +137,67 @@
};
}
-export { verifyAndGetDeviceList, createAndSignInitialDeviceList };
+async function signDeviceListUpdate(
+ deviceListPayload: RawDeviceList,
+): Promise<SignedDeviceList> {
+ const deviceID = await getContentSigningKey();
+ const rawDeviceList = JSON.stringify(deviceListPayload);
+
+ // don't sign device list if current device is not a primary one
+ if (deviceListPayload.devices[0] !== deviceID) {
+ return {
+ rawDeviceList,
+ };
+ }
+
+ const { olmAPI } = getConfig();
+ const curPrimarySignature = await olmAPI.signMessage(rawDeviceList);
+ return {
+ rawDeviceList,
+ curPrimarySignature,
+ };
+}
+
+async function fetchLatestDeviceList(
+ identityClient: IdentityServiceClient,
+ userID: string,
+): Promise<RawDeviceList> {
+ const deviceLists = await identityClient.getDeviceListHistoryForUser(userID);
+ if (deviceLists.length < 1) {
+ throw new Error('received empty device list history');
+ }
+
+ const lastSignedDeviceList = deviceLists[deviceLists.length - 1];
+ return rawDeviceListFromSignedList(lastSignedDeviceList);
+}
+
+async function addDeviceToDeviceList(
+ identityClient: IdentityServiceClient,
+ userID: string,
+ newDeviceID: string,
+) {
+ const { updateDeviceList } = identityClient;
+ invariant(
+ updateDeviceList,
+ 'updateDeviceList() should be defined on native. ' +
+ 'Are you calling it on a non-primary device?',
+ );
+
+ const { devices } = await fetchLatestDeviceList(identityClient, userID);
+ if (devices.includes(newDeviceID)) {
+ // the device was already on the device list
+ return;
+ }
+
+ const newDeviceList = composeRawDeviceList([...devices, newDeviceID]);
+ const signedDeviceList = await signDeviceListUpdate(newDeviceList);
+ await updateDeviceList(signedDeviceList);
+}
+
+export {
+ verifyAndGetDeviceList,
+ createAndSignInitialDeviceList,
+ fetchLatestDeviceList,
+ addDeviceToDeviceList,
+ signDeviceListUpdate,
+};
diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js
--- a/native/profile/secondary-device-qr-code-scanner.react.js
+++ b/native/profile/secondary-device-qr-code-scanner.react.js
@@ -7,6 +7,7 @@
import { View } from 'react-native';
import { parseDataFromDeepLink } from 'lib/facts/links.js';
+import { addDeviceToDeviceList } from 'lib/shared/device-list-utils.js';
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
import {
@@ -23,10 +24,7 @@
type PeerToPeerMessage,
} from 'lib/types/tunnelbroker/peer-to-peer-message-types.js';
import { qrCodeAuthMessageTypes } from 'lib/types/tunnelbroker/qr-code-auth-message-types.js';
-import {
- composeRawDeviceList,
- rawDeviceListFromSignedList,
-} from 'lib/utils/device-list-utils.js';
+import { rawDeviceListFromSignedList } from 'lib/utils/device-list-utils.js';
import { assertWithValidator } from 'lib/utils/validation-utils.js';
import type { ProfileNavigationProp } from './profile.react.js';
@@ -36,7 +34,6 @@
import {
composeTunnelbrokerQRAuthMessage,
parseTunnelbrokerQRAuthMessage,
- signDeviceListUpdate,
} from '../qr-code/qr-code-utils.js';
import { useStyles } from '../themes/colors.js';
import Alert from '../utils/alert.js';
@@ -90,40 +87,6 @@
await Promise.all(promises);
}, [identityContext, tunnelbrokerContext]);
- const addDeviceToList = React.useCallback(
- async (newDeviceID: string) => {
- const { getDeviceListHistoryForUser, updateDeviceList } =
- identityContext.identityClient;
- invariant(
- updateDeviceList,
- 'updateDeviceList() should be defined for primary device',
- );
-
- const authMetadata = await identityContext.getAuthMetadata();
- if (!authMetadata?.userID) {
- throw new Error('missing auth metadata');
- }
-
- const deviceLists = await getDeviceListHistoryForUser(
- authMetadata.userID,
- );
- invariant(deviceLists.length > 0, 'received empty device list history');
-
- const lastSignedDeviceList = deviceLists[deviceLists.length - 1];
- const deviceList = rawDeviceListFromSignedList(lastSignedDeviceList);
-
- const { devices } = deviceList;
- if (devices.includes(newDeviceID)) {
- return;
- }
-
- const newDeviceList = composeRawDeviceList([...devices, newDeviceID]);
- const signedDeviceList = await signDeviceListUpdate(newDeviceList);
- await updateDeviceList(signedDeviceList);
- },
- [identityContext],
- );
-
const tunnelbrokerMessageListener = React.useCallback(
async (message: TunnelbrokerMessage) => {
const encryptionKey = aes256Key.current;
@@ -239,7 +202,11 @@
if (!primaryDeviceID || !userID) {
throw new Error('missing auth metadata');
}
- await addDeviceToList(ed25519);
+ await addDeviceToDeviceList(
+ identityContext.identityClient,
+ userID,
+ ed25519,
+ );
const message = await composeTunnelbrokerQRAuthMessage(aes256, {
type: qrCodeAuthMessageTypes.DEVICE_LIST_UPDATE_SUCCESS,
userID,
@@ -259,7 +226,7 @@
navigation.goBack();
}
},
- [tunnelbrokerContext, addDeviceToList, identityContext, navigation],
+ [tunnelbrokerContext, identityContext, navigation],
);
const onCancelScan = React.useCallback(() => setScanned(false), []);
diff --git a/native/qr-code/qr-code-utils.js b/native/qr-code/qr-code-utils.js
--- a/native/qr-code/qr-code-utils.js
+++ b/native/qr-code/qr-code-utils.js
@@ -1,10 +1,6 @@
// @flow
import { hexToUintArray } from 'lib/media/data-utils.js';
-import type {
- RawDeviceList,
- SignedDeviceList,
-} from 'lib/types/identity-service-types.js';
import {
peerToPeerMessageTypes,
type QRCodeAuthMessage,
@@ -13,8 +9,6 @@
qrCodeAuthMessagePayloadValidator,
type QRCodeAuthMessagePayload,
} from 'lib/types/tunnelbroker/qr-code-auth-message-types.js';
-import { getConfig } from 'lib/utils/config.js';
-import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import {
convertBytesToObj,
@@ -58,29 +52,4 @@
return Promise.resolve(payload);
}
-async function signDeviceListUpdate(
- deviceListPayload: RawDeviceList,
-): Promise<SignedDeviceList> {
- const deviceID = await getContentSigningKey();
- const rawDeviceList = JSON.stringify(deviceListPayload);
-
- // don't sign device list if current device is not a primary one
- if (deviceListPayload.devices[0] !== deviceID) {
- return {
- rawDeviceList,
- };
- }
-
- const { olmAPI } = getConfig();
- const curPrimarySignature = await olmAPI.signMessage(rawDeviceList);
- return {
- rawDeviceList,
- curPrimarySignature,
- };
-}
-
-export {
- composeTunnelbrokerQRAuthMessage,
- parseTunnelbrokerQRAuthMessage,
- signDeviceListUpdate,
-};
+export { composeTunnelbrokerQRAuthMessage, parseTunnelbrokerQRAuthMessage };

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 26, 11:29 PM (15 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2586017
Default Alt Text
D12238.id40869.diff (7 KB)

Event Timeline