Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3386861
D11295.id37986.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D11295.id37986.diff
View Options
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
@@ -1,16 +1,32 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { View, Text } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import { qrCodeLinkURL } from 'lib/facts/links.js';
import { uintArrayToHexString } from 'lib/media/data-utils.js';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
+import type {
+ NonceChallenge,
+ SignedMessage,
+} from 'lib/types/identity-service-types.js';
+import {
+ tunnelbrokerMessageTypes,
+ type TunnelbrokerMessage,
+} 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 type { QRCodeSignInNavigationProp } from './qr-code-sign-in-navigator.react.js';
+import { commCoreModule } from '../native-modules.js';
import type { NavigationRoute } from '../navigation/route-names.js';
import { useStyles } from '../themes/colors.js';
import * as AES from '../utils/aes-crypto-module.js';
+import Alert from '../utils/alert.js';
import { getContentSigningKey } from '../utils/crypto-utils.js';
type QRCodeScreenProps = {
@@ -21,6 +37,83 @@
// eslint-disable-next-line no-unused-vars
function QRCodeScreen(props: QRCodeScreenProps): React.Node {
const [qrCodeValue, setQrCodeValue] = React.useState<?string>();
+ const [deviceKeys, setDeviceKeys] =
+ React.useState<?{ +deviceID: string, +aesKey: string }>();
+ const { setUnauthorizedDeviceID, addListener, removeListener } =
+ useTunnelbroker();
+ const identityContext = React.useContext(IdentityClientContext);
+ const identityClient = identityContext?.identityClient;
+
+ const tunnelbrokerMessageListener = React.useCallback(
+ async (message: TunnelbrokerMessage) => {
+ invariant(identityClient, 'identity context not set');
+ if (
+ !deviceKeys ||
+ message.type !== tunnelbrokerMessageTypes.MESSAGE_TO_DEVICE
+ ) {
+ return;
+ }
+
+ const innerMessage = JSON.parse(message.payload);
+ if (innerMessage.type !== peerToPeerMessageTypes.QR_CODE_AUTH_MESSAGE) {
+ return;
+ }
+ const qrCodeAuthMessage = parseQRAuthTunnelbrokerMessage(
+ deviceKeys.aesKey,
+ innerMessage,
+ );
+ if (
+ !qrCodeAuthMessage ||
+ qrCodeAuthMessage.type !==
+ qrCodeAuthMessageTypes.DEVICE_LIST_UPDATE_SUCCESS
+ ) {
+ return;
+ }
+ const { userID } = qrCodeAuthMessage;
+
+ try {
+ const nonce = await identityClient.generateNonce();
+ const nonceChallenge: NonceChallenge = { nonce };
+ const nonceMessage = JSON.stringify(nonceChallenge);
+ const signature = await commCoreModule.signMessage(nonceMessage);
+ const challengeResponse: SignedMessage = {
+ message: nonceMessage,
+ signature,
+ };
+
+ await identityClient.uploadKeysForRegisteredDeviceAndLogIn(
+ userID,
+ challengeResponse,
+ );
+ setUnauthorizedDeviceID(null);
+ } catch (err) {
+ console.error('Secondary device registration error:', err);
+ Alert.alert('Registration failed', 'Failed to upload device keys', [
+ { text: 'OK' },
+ ]);
+ }
+ },
+ [setUnauthorizedDeviceID, identityClient, deviceKeys],
+ );
+
+ React.useEffect(() => {
+ if (!deviceKeys) {
+ return () => {};
+ }
+ addListener(tunnelbrokerMessageListener);
+ setUnauthorizedDeviceID(deviceKeys.deviceID);
+
+ return () => {
+ removeListener(tunnelbrokerMessageListener);
+ setUnauthorizedDeviceID(null);
+ };
+ }, [
+ setUnauthorizedDeviceID,
+ deviceKeys,
+ addListener,
+ removeListener,
+ tunnelbrokerMessageListener,
+ ]);
const generateQRCode = React.useCallback(async () => {
try {
@@ -31,6 +124,7 @@
const url = qrCodeLinkURL(aesKeyAsHexString, ed25519Key);
setQrCodeValue(url);
+ setDeviceKeys({ deviceID: ed25519Key, aesKey: aesKeyAsHexString });
} catch (err) {
console.error('Failed to generate QR Code:', err);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 30, 6:33 AM (22 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2599953
Default Alt Text
D11295.id37986.diff (4 KB)
Attached To
Mode
D11295: [native] Upload secondary device keys when added to list
Attached
Detach File
Event Timeline
Log In to Comment