Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / keys / deviceConfirm.ts
blobcedaf55bbc5186692ff5e628bee565bee15fa67a
1 import { c } from 'ttag';
3 import { activateAuthDeviceConfig } from '@proton/shared/lib/api/authDevice';
4 import { getApiError } from '@proton/shared/lib/api/helpers/apiErrorHelper';
5 import type { Address, Api, DecryptedKey } from '@proton/shared/lib/interfaces';
7 import {
8     type AuthDeviceOutput,
9     type DeviceSecretData,
10     decryptAuthDeviceActivationToken,
11     encryptAuthDeviceSecret,
12     getValidActivation,
13 } from './device';
15 export class ConfirmAuthDeviceError extends Error {}
17 export const getAuthDeviceActivation = ({
18     addresses,
19     pendingAuthDevice,
20 }: {
21     addresses: Address[];
22     pendingAuthDevice: AuthDeviceOutput;
23 }) => {
24     const activation = getValidActivation({ addresses, pendingAuthDevice });
25     if (!activation) {
26         throw new ConfirmAuthDeviceError('Unable to find address for device');
27     }
28     return activation;
31 export const decryptAuthDeviceActivation = async ({
32     deviceID,
33     addressKeys,
34     token,
35 }: {
36     deviceID: string;
37     addressKeys: DecryptedKey[];
38     token: string;
39 }) => {
40     try {
41         const deviceSecretData = await decryptAuthDeviceActivationToken({
42             deviceID,
43             decryptionKeys: addressKeys.map(({ privateKey }) => privateKey),
44             armoredMessage: token,
45         });
46         return deviceSecretData;
47     } catch {
48         throw new ConfirmAuthDeviceError('Unable to decrypt activation token');
49     }
52 export const validateAuthDevice = ({
53     deviceSecretData,
54     confirmationCode,
55 }: {
56     deviceSecretData: DeviceSecretData;
57     confirmationCode: string;
58 }) => {
59     if (deviceSecretData.confirmationCode !== confirmationCode) {
60         throw new ConfirmAuthDeviceError(c('sso').t`Invalid confirmation code`);
61     }
64 export const activateAuthDevice = async ({
65     api,
66     keyPassword,
67     deviceSecretData,
68     pendingAuthDevice,
69 }: {
70     api: Api;
71     keyPassword: string;
72     deviceSecretData: DeviceSecretData;
73     pendingAuthDevice: AuthDeviceOutput;
74 }) => {
75     try {
76         const encryptedSecret = await encryptAuthDeviceSecret({
77             keyPassword,
78             deviceSecretData,
79         });
80         await api(
81             activateAuthDeviceConfig({
82                 DeviceID: pendingAuthDevice.ID,
83                 EncryptedSecret: encryptedSecret,
84             })
85         );
86     } catch (error) {
87         const { message } = getApiError(error);
88         throw new ConfirmAuthDeviceError(message || 'Failed to activate device');
89     }