Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32532703
D11295.1767153585.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D11295.1767153585.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,35 @@
// @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,
+ peerToPeerMessageValidator,
+} 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 +40,91 @@
// eslint-disable-next-line no-unused-vars
function QRCodeScreen(props: QRCodeScreenProps): React.Node {
const [qrCodeValue, setQrCodeValue] = React.useState<?string>();
+ const [qrData, setQRData] =
+ 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 (
+ !qrData ||
+ message.type !== tunnelbrokerMessageTypes.MESSAGE_TO_DEVICE
+ ) {
+ return;
+ }
+
+ let innerMessage;
+ try {
+ innerMessage = JSON.parse(message.payload);
+ } catch {
+ return;
+ }
+ if (
+ !peerToPeerMessageValidator.is(innerMessage) ||
+ innerMessage.type !== peerToPeerMessageTypes.QR_CODE_AUTH_MESSAGE
+ ) {
+ return;
+ }
+ const qrCodeAuthMessage = parseQRAuthTunnelbrokerMessage(
+ qrData.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, qrData],
+ );
+
+ React.useEffect(() => {
+ if (!qrData) {
+ return undefined;
+ }
+ addListener(tunnelbrokerMessageListener);
+ setUnauthorizedDeviceID(qrData.deviceID);
+
+ return () => {
+ removeListener(tunnelbrokerMessageListener);
+ setUnauthorizedDeviceID(null);
+ };
+ }, [
+ setUnauthorizedDeviceID,
+ qrData,
+ addListener,
+ removeListener,
+ tunnelbrokerMessageListener,
+ ]);
const generateQRCode = React.useCallback(async () => {
try {
@@ -31,6 +135,7 @@
const url = qrCodeLinkURL(aesKeyAsHexString, ed25519Key);
setQrCodeValue(url);
+ setQRData({ deviceID: ed25519Key, aesKey: aesKeyAsHexString });
} catch (err) {
console.error('Failed to generate QR Code:', err);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 31, 3:59 AM (6 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866812
Default Alt Text
D11295.1767153585.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