Page MenuHomePhabricator

D11296.id37993.diff
No OneTemporary

D11296.id37993.diff

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
@@ -10,8 +10,19 @@
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
import type { RawDeviceList } from 'lib/types/identity-service-types.js';
+import {
+ tunnelbrokerMessageTypes,
+ type TunnelbrokerMessage,
+} from 'lib/types/tunnelbroker/messages.js';
+import {
+ peerToPeerMessageTypes,
+ 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 { createQRAuthTunnelbrokerMessage } from 'lib/utils/qr-code-auth.js';
+import {
+ createQRAuthTunnelbrokerMessage,
+ parseQRAuthTunnelbrokerMessage,
+} from 'lib/utils/qr-code-auth.js';
import type { ProfileNavigationProp } from './profile.react.js';
import type { NavigationRoute } from '../navigation/route-names.js';
@@ -35,6 +46,9 @@
const tunnelbrokerContext = useTunnelbroker();
const identityContext = React.useContext(IdentityClientContext);
+ const aes256Key = React.useRef<?string>(null);
+ const secondaryDeviceID = React.useRef<?string>(null);
+
const addDeviceToList = React.useCallback(
async (newDeviceID: string) => {
invariant(identityContext, 'identity context not set');
@@ -75,6 +89,47 @@
[identityContext],
);
+ const tunnelbrokerMessageListener = React.useCallback(
+ async (message: TunnelbrokerMessage) => {
+ const encryptionKey = aes256Key.current;
+ const targetDeviceID = secondaryDeviceID.current;
+ if (!encryptionKey || !targetDeviceID) {
+ return;
+ }
+ if (message.type !== tunnelbrokerMessageTypes.MESSAGE_TO_DEVICE) {
+ return;
+ }
+
+ const innerMessage: PeerToPeerMessage = JSON.parse(message.payload);
+ if (innerMessage.type !== peerToPeerMessageTypes.QR_CODE_AUTH_MESSAGE) {
+ return;
+ }
+
+ const payload = parseQRAuthTunnelbrokerMessage(
+ encryptionKey,
+ innerMessage,
+ );
+ if (
+ payload?.type !==
+ qrCodeAuthMessageTypes.SECONDARY_DEVICE_REGISTRATION_SUCCESS
+ ) {
+ return;
+ }
+ Alert.alert('Device added', 'Device registered successfully', [
+ { text: 'OK' },
+ ]);
+ },
+ [tunnelbrokerContext],
+ );
+
+ React.useEffect(() => {
+ tunnelbrokerContext.addListener(tunnelbrokerMessageListener);
+
+ return () => {
+ tunnelbrokerContext.removeListener(tunnelbrokerMessageListener);
+ };
+ }, [tunnelbrokerMessageListener, tunnelbrokerContext]);
+
React.useEffect(() => {
void (async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
@@ -109,6 +164,8 @@
const keys = JSON.parse(decodeURIComponent(keysMatch));
const { aes256, ed25519 } = keys;
+ aes256Key.current = aes256;
+ secondaryDeviceID.current = ed25519;
void (async () => {
try {
diff --git a/native/qr-code/qr-code-screen.react.js b/native/qr-code/qr-code-screen.react.js
--- a/native/qr-code/qr-code-screen.react.js
+++ b/native/qr-code/qr-code-screen.react.js
@@ -19,7 +19,10 @@
} from 'lib/types/tunnelbroker/messages.js';
import { peerToPeerMessageTypes } from 'lib/types/tunnelbroker/peer-to-peer-message-types.js';
import { qrCodeAuthMessageTypes } from 'lib/types/tunnelbroker/qr-code-auth-message-types.js';
-import { parseQRAuthTunnelbrokerMessage } from 'lib/utils/qr-code-auth.js';
+import {
+ createQRAuthTunnelbrokerMessage,
+ parseQRAuthTunnelbrokerMessage,
+} from 'lib/utils/qr-code-auth.js';
import type { QRCodeSignInNavigationProp } from './qr-code-sign-in-navigator.react.js';
import { commCoreModule } from '../native-modules.js';
@@ -39,11 +42,41 @@
const [qrCodeValue, setQrCodeValue] = React.useState<?string>();
const [deviceKeys, setDeviceKeys] =
React.useState<?{ +deviceID: string, +aesKey: string }>();
- const { setUnauthorizedDeviceID, addListener, removeListener } =
- useTunnelbroker();
+ const [primaryDeviceID, setPrimaryDeviceID] = React.useState<?string>();
+ const {
+ setUnauthorizedDeviceID,
+ addListener,
+ removeListener,
+ connected: tunnelbrokerConnected,
+ isAuthorized,
+ sendMessage,
+ } = useTunnelbroker();
const identityContext = React.useContext(IdentityClientContext);
const identityClient = identityContext?.identityClient;
+ React.useEffect(() => {
+ if (
+ !(tunnelbrokerConnected && isAuthorized && primaryDeviceID && deviceKeys)
+ ) {
+ return;
+ }
+
+ const message = createQRAuthTunnelbrokerMessage(deviceKeys.aesKey, {
+ type: qrCodeAuthMessageTypes.SECONDARY_DEVICE_REGISTRATION_SUCCESS,
+ });
+ console.log('SECONDARY MESSAGE', message);
+ void sendMessage({
+ deviceID: primaryDeviceID,
+ payload: JSON.stringify(message),
+ });
+ }, [
+ tunnelbrokerConnected,
+ isAuthorized,
+ sendMessage,
+ primaryDeviceID,
+ deviceKeys,
+ ]);
+
const tunnelbrokerMessageListener = React.useCallback(
async (message: TunnelbrokerMessage) => {
invariant(identityClient, 'identity context not set');
@@ -69,7 +102,9 @@
) {
return;
}
- const { userID } = qrCodeAuthMessage;
+ const { primaryDeviceID: receivedPrimaryDeviceID, userID } =
+ qrCodeAuthMessage;
+ setPrimaryDeviceID(receivedPrimaryDeviceID);
try {
const nonce = await identityClient.generateNonce();

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 1, 6:24 PM (21 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2400501
Default Alt Text
D11296.id37993.diff (5 KB)

Event Timeline